[#configuration] = Choosing a Filter Configuration :idprefix: configuration_ Boost.Bloom offers a plethora of compile-time and run-time configuration options, so it may be difficult to make a choice. If you're aiming for a given FPR or have a particular capacity in mind and you'd like to choose the most appropriate filter type, the following chart may come handy. image::fpr_c.png[align=center, title="FPR vs. _c_ for different filter types."] The chart plots FPR vs. _c_ (capacity / number of elements inserted) for several `boost::bloom::filter`+++s+++ where `K` has been set to its optimum value (minimum FPR) as shown in the table below. +++

| c = capacity / number of elements inserted
--- | ---
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24
`filter<T,1,block<uint32_t,K>>` | 3 | 3 | 3 | 4 | 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 6 | 6 | 7 | 7 | 7 | 7 | 7 | 7 | 7
`filter<T,1,block<uint32_t,K>,1>` | 2 | 3 | 4 | 4 | 4 | 4 | 5 | 5 | 5 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 7 | 7 | 7 | 7 | 7
`filter<T,1,block<uint64_t,K>>` | 2 | 3 | 4 | 4 | 5 | 5 | 5 | 5 | 5 | 6 | 6 | 6 | 6 | 6 | 7 | 7 | 7 | 7 | 7 | 7 | 7
`filter<T,1,block<uint64_t,K>,1>` | 2 | 3 | 4 | 4 | 4 | 5 | 6 | 6 | 6 | 7 | 7 | 7 | 7 | 7 | 8 | 8 | 8 | 8 | 8 | 9 | 9
`filter<T,1,multiblock<uint32_t,K>>` | 3 | 3 | 4 | 5 | 6 | 6 | 8 | 8 | 8 | 8 | 9 | 9 | 9 | 10 | 13 | 13 | 15 | 15 | 15 | 16 | 16
`filter<T,1,block<uint64_t[8],K>>` | 4 | 4 | 4 | 5 | 5 | 6 | 7 | 7 | 7 | 8 | 8 | 9 | 9 | 10 | 10 | 11 | 12 | 12 | 12 | 12 | 12
`filter<T,1,multiblock<uint32_t,K>,1>` | 3 | 3 | 4 | 5 | 6 | 6 | 7 | 7 | 8 | 8 | 9 | 9 | 10 | 10 | 12 | 12 | 14 | 14 | 14 | 14 | 15
`filter<T,1,block<uint64_t[8],K>,1>` | 3 | 3 | 4 | 5 | 6 | 6 | 7 | 7 | 7 | 8 | 8 | 8 | 10 | 11 | 11 | 12 | 12 | 12 | 12 | 12 | 13
`filter<T,1,multiblock<uint64_t,K>>` | 4 | 4 | 5 | 5 | 6 | 6 | 6 | 7 | 8 | 8 | 10 | 10 | 12 | 13 | 14 | 15 | 15 | 15 | 15 | 16 | 17
`filter<T,1,multiblock<uint64_t,K>,1>` | 3 | 3 | 4 | 5 | 5 | 6 | 6 | 7 | 9 | 10 | 10 | 11 | 11 | 12 | 12 | 13 | 13 | 13 | 15 | 16 | 16
`filter<T,K>` | 3 | 4 | 4 | 5 | 5 | 6 | 6 | 8 | 8 | 9 | 10 | 11 | 12 | 13 | 13 | 13 | 14 | 16 | 16 | 16 | 17

+++ Let's see how this can be used by way of an example. Suppose we plan to insert 10M elements and want to keep the FPR at 10^−4^. The chart gives us five different values of _c_ (the array capacity divided by the number of elements, in our case 10M): * `filter` -> _c_ ≅ 19 bits per element * `filter, 1>` -> _c_ ≅ 20 bits per element * `filter>` -> _c_ ≅ 21 bits per element * `filter, 1>` -> _c_ ≅ 21 bits per element * `filter, 1>` -> _c_ ≅ 21.5 bits per element * `filter>` -> _c_ ≅ 22 bits per element * `filter>` -> _c_ ≅ 23 bits per element These options have different tradeoffs in terms of space used and performance. If we choose `filter, 1>` as a compromise (or better yet, `filter, 1>`), the only remaining step is to consult the value of `K` in the table for _c_ = 21 or 22, and we get our final configuration: [source,subs="+macros,+quotes"] ----- using my_filter=filter
    , 1>;
    -----

    The resulting filter can be constructed in any of the following ways:

    [source]
    -----
    // 1) calculate the capacity from the value of c we got from the chart
    my_filter f((std::size_t)(10'000'000 * 21.5));

    // 2) let the library calculate the capacity from n and target fpr
    // expect some deviation from the capacity in 1)
    my_filter f(10'000'000, 1E-4);

    // 3) equivalent to 2)
    my_filter f(my_filter::capacity_for(10'000'000, 1E-4));
    -----