2222#include < bitcoin/system.hpp>
2323#include < bitcoin/database/define.hpp>
2424
25- // [-------------------- sieve-----------][--------------link--------------]
26- // [[selector ][--------screens---------]][--------------link--------------]
25+ // [------------------sieve-----------][--------------link--------------]
26+ // [[select ][--------screens---------]][--------------link--------------]
2727
2828// [[111][1111111111111111111111111111]] empty/default
2929// [[000][1111111111111111111111111111]] 1 screen
4949namespace libbitcoin {
5050namespace database {
5151
52+ // Suppress bogus warnings to use constexpr when function is consteval.
53+ BC_PUSH_WARNING (USE_CONSTEXPR_FOR_FUNCTION)
54+ BC_PUSH_WARNING (NO_ARRAY_INDEXING)
55+
5256TEMPLATE
5357constexpr CLASS::sieve () NOEXCEPT
5458 : sieve(empty)
@@ -87,87 +91,95 @@ constexpr CLASS::type CLASS::masks(size_t row, size_t column) const NOEXCEPT
8791TEMPLATE
8892constexpr bool CLASS::screened (type fingerprint) const NOEXCEPT
8993{
90- using namespace system ;
91- if constexpr ( is_zero (limit))
94+ if constexpr (disabled)
95+ {
9296 return true ;
93-
94- const auto row = shift_right (sieve_, screen_bits);
95- if (row == limit)
97+ }
98+ else
9699 {
97- if (sieve_ == empty)
98- return false ;
100+ using namespace system ;
101+ const auto row = shift_right (sieve_, screen_bits);
102+ if (row == limit)
103+ {
104+ if (sieve_ == empty)
105+ return false ;
99106
100- if (sieve_ == saturated)
101- return true ;
102- }
107+ if (sieve_ == saturated)
108+ return true ;
109+ }
103110
104- // Compare masked fingerprint to masked sieve, for all masks of the screen.
105- for (type segment{}; segment <= row; ++segment)
106- {
107- const auto mask = masks (row, segment);
108- if (bit_and (fingerprint, mask) == bit_and (sieve_, mask))
109- return true ;
110- }
111+ // Compare masked fingerprint to sieve, for all masks of screen.
112+ for (type segment{}; segment <= row; ++segment)
113+ {
114+ const auto mask = masks (row, segment);
115+ if (bit_and (fingerprint, mask) == bit_and (sieve_, mask))
116+ return true ;
117+ }
111118
112- // Not empty, not saturated, not aligned with active screen (full if max).
113- return false ;
119+ // Not empty or saturated, not aligned with screen (full if max).
120+ return false ;
121+ }
114122}
115123
116124TEMPLATE
117125constexpr bool CLASS::screen (type fingerprint) NOEXCEPT
118126{
119- using namespace system ;
120- if constexpr (is_zero (limit))
121- return false ;
122-
123- auto row = shift_right (sieve_, screen_bits);
124- if (row == limit)
127+ if constexpr (disabled)
125128 {
126- if (sieve_ == empty)
127- {
128- // Reset empty sentinel (not screened) for first screen.
129- zeroize (row);
130- }
131- else
132- {
133- // Sieve was full, now saturated (all screened).
134- sieve_ = saturated;
135- return false ;
136- }
129+ return false ;
137130 }
138131 else
139132 {
140- if (screened (fingerprint))
133+ using namespace system ;
134+ auto row = shift_right (sieve_, screen_bits);
135+ if (row == limit)
141136 {
142- // Screened, bucket may contain element.
143- return false ;
137+ if (sieve_ == empty)
138+ {
139+ // Reset empty sentinel (not screened) for first screen.
140+ zeroize (row);
141+ }
142+ else
143+ {
144+ // Sieve was full, now saturated (all screened).
145+ sieve_ = saturated;
146+ return false ;
147+ }
144148 }
145149 else
146150 {
147- // Not screened, empty, or full - add screen.
148- ++row;
151+ if (screened (fingerprint))
152+ {
153+ // Screened, bucket may contain element.
154+ return false ;
155+ }
156+ else
157+ {
158+ // Not screened, empty, or full - add screen.
159+ ++row;
160+ }
149161 }
150- }
151162
152- // Both indexes are screen selector, as each new screen adds one mask.
153- const auto mask = masks (row, row);
163+ // Both indexes are screen selector, as each new screen adds one mask.
164+ const auto mask = masks (row, row);
154165
155- // Merge incremented selector, current sieve, and new fingerprint.
156- sieve_ = bit_or
157- (
158- shift_left (row, screen_bits),
159- bit_and
166+ // Merge incremented selector, current sieve, and new fingerprint.
167+ sieve_ = bit_or
160168 (
161- selector_mask ,
162- bit_or
169+ shift_left (row, screen_bits) ,
170+ bit_and
163171 (
164- bit_and (fingerprint, mask),
165- bit_and (sieve_, bit_not (mask))
172+ selector_mask,
173+ bit_or
174+ (
175+ bit_and (fingerprint, mask),
176+ bit_and (sieve_, bit_not (mask))
177+ )
166178 )
167- )
168- );
179+ );
169180
170- return true ;
181+ return true ;
182+ }
171183}
172184
173185// protected/static
@@ -178,7 +190,7 @@ CONSTEVAL CLASS::offsets_t CLASS::generate_offsets() NOEXCEPT
178190
179191 // Generate compression offsets at compile, generally 16 or 32 elements.
180192 offsets_t offsets{};
181- for (size_t index{}; index < screens; ++index)
193+ for (type index{}; index < screens; ++index)
182194 offsets[index] = to_half (ceilinged_multiply (index, add1 (index)));
183195
184196 return offsets;
@@ -208,7 +220,11 @@ CONSTEVAL CLASS::masks_t CLASS::generate_masks() NOEXCEPT
208220 return div + to_int (column < mod);
209221 };
210222
223+ // Start with all screen bits set.
211224 masks (0 , 0 ) = first_mask;
225+
226+ // Progressively divide previous row masks into subsequent row.
227+ // Each row adds one mask, with previous row masks sacrificing bits for it.
212228 for (type row = 1 ; row < screens; ++row)
213229 {
214230 for (type col = 0 ; col < row; ++col)
@@ -233,9 +249,17 @@ CONSTEVAL CLASS::masks_t CLASS::generate_masks() NOEXCEPT
233249 }
234250 }
235251
252+ // Unset last row high order screen bit to avoid sentinel conflict.
253+ // This may result in one empty mask, and therefore a false positive.
254+ for (type col = 0 ; col < screens; ++col)
255+ set_right_into (masks (sub1 (screens), col), sentinel, false );
256+
236257 return out;
237258}
238259
260+ BC_POP_WARNING ()
261+ BC_POP_WARNING ()
262+
239263} // namespace database
240264} // namespace libbitcoin
241265
0 commit comments