HIBF 1.0.0-rc.1
Loading...
Searching...
No Matches
interleaved_bloom_filter.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2026, Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2026, Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <algorithm> // for fill
13#include <array> // for array
14#include <cstddef> // for size_t
15#include <cstdint> // for uint16_t, uint64_t, uint32_t
16#include <memory> // for addressof
17#include <ranges> // for forward_range, integral, range, range_value_t, unsigned_integral
18#include <type_traits> // for false_type, remove_cvref_t
19#include <vector> // for vector, operator==
20
21#include <cereal/cereal.hpp> // for make_nvp
22#include <cereal/macros.hpp> // for CEREAL_SERIALIZE_FUNCTION_NAME
23#include <cereal/types/base_class.hpp> // for base_class
24#include <cereal/types/vector.hpp> // IWYU pragma: keep
25
26#include <hibf/cereal/concepts.hpp> // for cereal_archive
27#include <hibf/contrib/std/enumerate_view.hpp> // for enumerate
28#include <hibf/misc/bit_vector.hpp> // for bit_vector
29#include <hibf/misc/counting_vector.hpp> // for counting_vector
30#include <hibf/misc/next_multiple_of_64.hpp> // for next_multiple_of_64
31#include <hibf/misc/unreachable.hpp> // for assert, unreachable, forward
32#include <hibf/platform.hpp> // for HIBF_HAS_AVX512
33
34namespace seqan::hibf
35{
36
37// config.hpp -> misc/insert_iterator.hpp (Needs interleaved_bloom_filter to be a complete class)
38struct config;
42struct inspector;
43
49{
50 size_t value;
51};
52
58{
59 size_t value;
60};
61
67{
68 size_t value;
69};
70
76{
77 size_t value;
78};
79
85{
86 double value;
87};
88
94{
95 bool value;
96};
97
162{
163private:
166
168 template <typename t>
169 friend struct cereal::base_class;
170
173
175 size_t bins{};
177 size_t technical_bins{};
179 size_t bin_size_{};
181 size_t hash_shift{};
183 size_t bin_words{};
185 size_t hash_funs{};
187 static constexpr std::array<size_t, 5> hash_seeds{13572355802537770549ULL, // 2**64 / (e/2)
188 13043817825332782213ULL, // 2**64 / sqrt(2)
189 10650232656628343401ULL, // 2**64 / sqrt(3)
190 16499269484942379435ULL, // 2**64 / (sqrt(5)/2)
191 4893150838803335377ULL}; // 2**64 / (3*pi/5)
192
200 [[gnu::always_inline]] inline constexpr size_t hash_and_fit(size_t h, size_t const seed) const
201 {
202 h *= seed;
203 assert(hash_shift < 64);
204 h ^= h >> hash_shift; // XOR and shift higher bits into lower bits
205 h *= 11400714819323198485ULL; // = 2^64 / golden_ration, to expand h to 64 bit range
206 // Use fastrange (integer modulo without division).
207 h = static_cast<uint64_t>((static_cast<__uint128_t>(h) * static_cast<__uint128_t>(bin_size_)) >> 64);
208 h *= technical_bins;
209 return h;
210 }
211
212public:
213 class containment_agent_type; // documented upon definition below
214 template <std::integral value_t>
215 class counting_agent_type; // documented upon definition below
216 class membership_agent_type; // documented upon definition below
217
225 interleaved_bloom_filter & operator=(interleaved_bloom_filter &&) noexcept = default;
227
247 seqan::hibf::bin_count const bins_,
248 seqan::hibf::bin_size const size,
249 seqan::hibf::hash_function_count const funs = seqan::hibf::hash_function_count{2u},
252
264 interleaved_bloom_filter(config & configuration, size_t const max_bin_elements = 0u);
266
282 void emplace(size_t const value, bin_index const bin) noexcept;
283
293 void clear(bin_index const bin) noexcept;
294
306 template <typename rng_t>
307 void clear(rng_t && bin_range) noexcept
308 {
309 static_assert(std::ranges::forward_range<rng_t>, "The range of bins to clear must model a forward_range.");
311 "The reference type of the range to clear must be seqan::hibf::bin_index.");
312#ifndef NDEBUG
313 for (auto && bin : bin_range)
314 assert(bin.value < technical_bins);
315#endif // NDEBUG
316
317 for (size_t offset = 0, i = 0; i < bin_size_; offset += technical_bins, ++i)
318 for (auto && bin : bin_range)
319 (*this)[bin.value + offset] = 0;
320 }
321
343 bool try_increase_bin_number_to(bin_count const new_bin_count) noexcept;
344
367 void increase_bin_number_to(bin_count const new_bin_count);
369
385
397 template <typename value_t = uint16_t>
402
414 membership_agent_type membership_agent() const;
416
423 size_t hash_function_count() const noexcept
424 {
425 return hash_funs;
426 }
427
431 size_t bin_count() const noexcept
432 {
433 return bins;
434 }
435
439 size_t bin_size() const noexcept
440 {
441 return bin_size_;
442 }
443
447 size_t bit_size() const noexcept
448 {
449 return base_t::size();
450 }
452
456 constexpr bool operator==(interleaved_bloom_filter const &) const = default;
458
469 using base_t::data;
471
479
481 bool track_occupancy{false};
482
486 static constexpr uint32_t version{1};
487
494 template <cereal_archive archive_t>
495 void CEREAL_SERIALIZE_FUNCTION_NAME(archive_t & archive)
496 {
497 uint32_t parsed_version{version};
498 archive(cereal::make_nvp("version", parsed_version));
499 archive(bins);
500 archive(technical_bins);
501 archive(bin_size_);
502 archive(hash_shift);
503 archive(bin_words);
504 archive(hash_funs);
505 archive(cereal::base_class<base_t>(this));
506 archive(occupancy);
507 archive(track_occupancy);
508 }
510};
511
523{
524private:
526 interleaved_bloom_filter const * ibf_ptr{nullptr};
527
529 std::array<size_t, 5> bloom_filter_indices;
530
532 bit_vector result_buffer;
533
534public:
542 containment_agent_type & operator=(containment_agent_type &&) noexcept = default;
544
550 ibf_ptr(std::addressof(ibf)),
551 result_buffer(ibf.bin_count())
552 {}
554
575 [[nodiscard]] bit_vector const & bulk_contains(size_t const value) & noexcept;
576
578 [[nodiscard]] bit_vector const & bulk_contains(size_t const value) && noexcept = delete;
580};
581
586
596template <std::integral value_t>
598{
599private:
601 containment_agent_type containment_agent;
602
604 counting_vector<value_t> result_buffer;
605
606public:
614 counting_agent_type & operator=(counting_agent_type &&) noexcept = default;
615 ~counting_agent_type() = default;
616
621 explicit counting_agent_type(interleaved_bloom_filter const & ibf) :
622 containment_agent(ibf),
623#if !HIBF_HAS_AVX512
624 result_buffer(ibf.bin_count())
625 {}
626#else
627 // AVX512 will access result_buffer's memory in chunks, so we need to make sure that we allocate enough memory
628 // such that the last chunk is not out of bounds.
629 result_buffer(next_multiple_of_64(ibf.bin_count())) // Ensure large enough capacity.
630 {
631 result_buffer.resize(ibf.bin_count()); // Resize to actual requested size.
632 // Silences llvm's ASAN container-overflow warning.
633# if defined(_LIBCPP_VERSION)
634# if __has_feature(address_sanitizer)
636 result_buffer.data() + result_buffer.capacity(),
637 result_buffer.data() + result_buffer.size(),
638 result_buffer.data() + result_buffer.capacity());
639# endif
640# endif
641 }
642#endif
643
645
668 template <std::ranges::range value_range_t>
669 [[nodiscard]] counting_vector<value_t> const & bulk_count(value_range_t && values) & noexcept
670 {
671 static_assert(std::ranges::input_range<value_range_t>, "The values must model input_range.");
673 "An individual value must be an unsigned integral.");
674
675 std::ranges::fill(result_buffer, 0);
676
677 for (auto && value : values)
678 result_buffer += containment_agent.bulk_contains(value);
679
680 return result_buffer;
681 }
682
684 template <std::ranges::range value_range_t>
685 [[nodiscard]] counting_vector<value_t> const & bulk_count(value_range_t && values) && noexcept = delete;
687};
688
700{
701private:
703 counting_agent_type<uint16_t> counting_agent;
704
706 std::vector<uint64_t> result_buffer;
707
708public:
716 membership_agent_type & operator=(membership_agent_type &&) noexcept = default;
718
723 explicit membership_agent_type(interleaved_bloom_filter const & ibf) :
724 counting_agent(ibf),
725 result_buffer(ibf.bin_count())
726 {}
728
736 {}
737
760 template <std::ranges::forward_range value_range_t>
761 [[nodiscard]] std::vector<uint64_t> const & membership_for(value_range_t && values,
762 uint16_t const threshold) & noexcept
763 {
764 static_assert(std::ranges::forward_range<value_range_t>, "The values must model forward_range.");
766 "An individual value must be an unsigned integral.");
767
768 result_buffer.clear();
769
770 auto & counts_per_bin = counting_agent.bulk_count(std::forward<value_range_t>(values));
771
772 if (result_buffer.capacity() < counts_per_bin.size())
774
775 for (auto [bin, count] : seqan::stl::views::enumerate(counts_per_bin))
776 if (count >= threshold)
777 result_buffer.emplace_back(bin);
778
779 return result_buffer;
780 }
781
783 template <std::ranges::forward_range value_range_t>
784 [[nodiscard]] std::vector<uint64_t> const & membership_for(value_range_t && values,
785 uint16_t const threshold) && noexcept = delete;
787
789 // GCOVR_EXCL_START
790 template <typename t>
791 struct always_false : std::false_type
792 {};
793
794 template <typename t = void>
795 [[nodiscard]] bit_vector const & bulk_contains(size_t const) & noexcept
796 {
797 static_assert(
798 always_false<t>::value,
799 "The functionality of the membership_agent has been changed to be analogous to the "
800 "hierarchical_interleaved_bloom_filter's version. As such, the interleaved_bloom_filter's membership_agent "
801 "now only offers membership_for, which returns bin indices that exceed a given threshold when querying a "
802 "range of values. bulk_contains is now part of a new agent: containment_agent. If you want to use "
803 "bulk_contains, change ibf.membership_agent() to ibf.containment_agent().");
805 }
806
807 [[nodiscard]] bit_vector const & bulk_contains(size_t const) && noexcept = delete;
808 // GCOVR_EXCL_STOP
810};
811
816
817} // namespace seqan::hibf
Provides seqan::hibf::bit_vector.
T capacity(T... args)
An bit vector.
Definition bit_vector.hpp:66
constexpr size_type size() const noexcept
Returns the number of elements.
Definition bit_vector.hpp:651
constexpr size_t count() const noexcept
Returns the number of bits that are set to true.
Definition bit_vector.hpp:630
A data structure that behaves like a std::vector and can be used to consolidate the results of multip...
Definition counting_vector.hpp:145
Manages containment queries for the seqan::hibf::interleaved_bloom_filter.
Definition interleaved_bloom_filter.hpp:523
containment_agent_type(containment_agent_type const &)=default
Defaulted.
bit_vector const & bulk_contains(size_t const value) &noexcept
Determines containment (set membership) of a given value.
containment_agent_type(containment_agent_type &&) noexcept=default
Defaulted.
bit_vector const & bulk_contains(size_t const value) &&noexcept=delete
Deleted. Calling this function on a temporary would result in a dangling reference.
containment_agent_type & operator=(containment_agent_type const &)=default
Defaulted.
Manages counting ranges of values for the seqan::hibf::interleaved_bloom_filter.
Definition interleaved_bloom_filter.hpp:598
counting_vector< value_t > const & bulk_count(value_range_t &&values) &noexcept
Counts the occurrences in each bin for all values in a range.
Definition interleaved_bloom_filter.hpp:669
counting_vector< value_t > const & bulk_count(value_range_t &&values) &&noexcept=delete
Deleted. Calling this function on a temporary would result in a dangling reference.
counting_agent_type(counting_agent_type const &)=default
Defaulted.
counting_agent_type(counting_agent_type &&) noexcept=default
Defaulted.
counting_agent_type & operator=(counting_agent_type const &)=default
Defaulted.
Manages membership queries for the seqan::hibf::interleaved_bloom_filter.
Definition interleaved_bloom_filter.hpp:700
membership_agent_type(membership_agent_type const &)=default
Defaulted.
void sort_results()
Has no effect.
Definition interleaved_bloom_filter.hpp:735
std::vector< uint64_t > const & membership_for(value_range_t &&values, uint16_t const threshold) &&noexcept=delete
Deleted. Calling this function on a temporary would result in a dangling reference.
membership_agent_type(membership_agent_type &&) noexcept=default
Defaulted.
std::vector< uint64_t > const & membership_for(value_range_t &&values, uint16_t const threshold) &noexcept
Determines set membership for all bins contained in this index, based on values and the threshold.
Definition interleaved_bloom_filter.hpp:761
membership_agent_type & operator=(membership_agent_type const &)=default
Defaulted.
The IBF binning directory. A data structure that efficiently answers set-membership queries for multi...
Definition interleaved_bloom_filter.hpp:162
bool track_occupancy
Whether to track the occupancy of the bins.
Definition interleaved_bloom_filter.hpp:481
std::vector< size_t > occupancy
Contains the number of unique values inserted into each bin.
Definition interleaved_bloom_filter.hpp:478
size_t bit_size() const noexcept
Returns the size of the underlying bitvector.
Definition interleaved_bloom_filter.hpp:447
interleaved_bloom_filter(config &configuration, size_t const max_bin_elements=0u)
Construct an Interleaved Bloom Filter.
interleaved_bloom_filter()=default
Defaulted.
counting_agent_type< value_t > counting_agent() const
Returns a seqan::hibf::interleaved_bloom_filter::counting_agent_type to be used for counting.
Definition interleaved_bloom_filter.hpp:398
void increase_bin_number_to(bin_count const new_bin_count)
Increases the number of bins stored in the Interleaved Bloom Filter.
friend struct cereal::base_class
Allow cereal to cast the IBF into its base class.
Definition interleaved_bloom_filter.hpp:169
size_t hash_function_count() const noexcept
Returns the number of hash functions used in the Interleaved Bloom Filter.
Definition interleaved_bloom_filter.hpp:423
void emplace(size_t const value, bin_index const bin) noexcept
Inserts a value into a specific bin.
void clear(bin_index const bin) noexcept
Clears a specific bin.
interleaved_bloom_filter & operator=(interleaved_bloom_filter const &)=default
Defaulted.
bool try_increase_bin_number_to(bin_count const new_bin_count) noexcept
Tries increasing the number of bins stored in the Interleaved Bloom Filter without reallocating memor...
void clear(rng_t &&bin_range) noexcept
Clears a range of bins.
Definition interleaved_bloom_filter.hpp:307
membership_agent_type membership_agent() const
Returns a seqan::hibf::interleaved_bloom_filter::membership_agent_type to be used for lookup.
Definition interleaved_bloom_filter.hpp:812
containment_agent_type containment_agent() const
Returns a seqan::hibf::interleaved_bloom_filter::containment_agent_type to be used for lookup.
Definition interleaved_bloom_filter.hpp:582
friend struct seqan::hibf::inspector
Allow access to private members. Used for util/inspect.
Definition interleaved_bloom_filter.hpp:172
static constexpr uint32_t version
The version of the HIBF.
Definition interleaved_bloom_filter.hpp:486
interleaved_bloom_filter(interleaved_bloom_filter const &)=default
Defaulted.
interleaved_bloom_filter(interleaved_bloom_filter &&) noexcept=default
Defaulted.
size_t bin_size() const noexcept
Returns the size of a single bin that the Interleaved Bloom Filter manages.
Definition interleaved_bloom_filter.hpp:439
size_t bin_count() const noexcept
Returns the number of bins that the Interleaved Bloom Filter manages.
Definition interleaved_bloom_filter.hpp:431
T clear(T... args)
Provides seqan::hibf::counting_vector.
T data(T... args)
T emplace_back(T... args)
T fill(T... args)
constexpr size_t next_multiple_of_64(size_t const value) noexcept
Returns the smallest integer that is greater or equal to value and a multiple of 64....
Definition next_multiple_of_64.hpp:18
T is_base_of_v
Provides platform and dependency checks.
T resize(T... args)
T size(T... args)
A strong type that represents the number of bins for the seqan::hibf::interleaved_bloom_filter.
Definition interleaved_bloom_filter.hpp:49
A strong type that represents the bin index for the seqan::hibf::interleaved_bloom_filter.
Definition interleaved_bloom_filter.hpp:76
A strong type that represents the number of bits for each bin in the seqan::hibf::interleaved_bloom_f...
Definition interleaved_bloom_filter.hpp:58
The configuration used to build an (H)IBF.
Definition config.hpp:76
A strong type that represents the empty bin fraction for the seqan::hibf::interleaved_bloom_filter.
Definition interleaved_bloom_filter.hpp:85
A strong type that represents the number of hash functions for the seqan::hibf::interleaved_bloom_fil...
Definition interleaved_bloom_filter.hpp:67
A strong type that represents whether to track occupancy for the seqan::hibf::interleaved_bloom_filte...
Definition interleaved_bloom_filter.hpp:94
Provides seqan::hibf::unreachable.
void unreachable()
Marks unreachable code paths.
Definition unreachable.hpp:37