MCPcopy Create free account
hub / github.com/ashvardanian/StringZilla / test_hash_equivalence

Function test_hash_equivalence

scripts/test_stringzilla.cpp:261–323  ·  view source on GitHub ↗

* @brief Hashes a string and compares the output between a serial and hardware-specific SIMD backend. * * The test covers increasingly long and complex strings, starting with "abcabc..." repetitions and * progressing towards corner cases like empty strings, all-zero inputs, zero seeds, and so on. */

Source from the content-addressed store, hash-verified

259 * progressing towards corner cases like empty strings, all-zero inputs, zero seeds, and so on.
260 */
261void test_hash_equivalence( //
262 sz_hash_t hash_base, sz_hash_state_init_t init_base, //
263 sz_hash_state_update_t stream_base, sz_hash_state_digest_t fold_base, //
264 sz_hash_t hash_simd, sz_hash_state_init_t init_simd, //
265 sz_hash_state_update_t stream_simd, sz_hash_state_digest_t fold_simd) {
266
267 auto test_on_seed = [&](std::string text, sz_u64_t seed) {
268 // Compute the entire hash at once, expecting the same output
269 sz_u64_t result_base = hash_base(text.data(), text.size(), seed);
270 sz_u64_t result_simd = hash_simd(text.data(), text.size(), seed);
271 assert(result_base == result_simd);
272
273 // Compare incremental hashing across platforms
274 sz_hash_state_t state_base, state_simd;
275 init_base(&state_base, seed);
276 init_simd(&state_simd, seed);
277 assert(sz_hash_state_equal(&state_base, &state_base) == sz_true_k); // Self-equality
278 assert(sz_hash_state_equal(&state_simd, &state_simd) == sz_true_k); // Self-equality
279 assert(sz_hash_state_equal(&state_base, &state_simd) == sz_true_k); // Same across platforms
280
281 // Let's also create an intentionally misaligned version of the state,
282 // assuming some of the SIMD instructions may require alignment.
283 sz_align_(64) char state_misaligned_buffer[sizeof(sz_hash_state_t) + 1];
284 sz_hash_state_t &state_misaligned = *reinterpret_cast<sz_hash_state_t *>(state_misaligned_buffer + 1);
285 init_simd(&state_misaligned, seed);
286 assert(sz_hash_state_equal(&state_base, &state_misaligned) == sz_true_k); // Same across platforms
287
288 // Try breaking those strings into arbitrary chunks, expecting the same output in the streaming mode.
289 // The length of each chunk and the number of chunks will be determined with a coin toss.
290 iterate_in_random_slices(text, [&](std::string slice) {
291 stream_base(&state_base, slice.data(), slice.size());
292 stream_simd(&state_simd, slice.data(), slice.size());
293 assert(sz_hash_state_equal(&state_base, &state_simd) == sz_true_k); // Same across platforms
294
295 stream_simd(&state_misaligned, slice.data(), slice.size());
296 assert(sz_hash_state_equal(&state_base, &state_misaligned) == sz_true_k); // Same across platforms
297
298 result_base = fold_base(&state_base);
299 result_simd = fold_simd(&state_simd);
300 assert(result_base == result_simd);
301 sz_u64_t result_misaligned = fold_simd(&state_misaligned);
302 assert(result_base == result_misaligned);
303 });
304 };
305
306 // Let's try different-length strings repeating a "abc" pattern:
307 std::vector<sz_u64_t> seeds = {
308 0u,
309 42u, //
310 std::numeric_limits<sz_u32_t>::max(), //
311 std::numeric_limits<sz_u64_t>::max(), //
312 };
313 for (auto seed : seeds)
314 for (std::size_t copies = 1; copies != 100; ++copies) //
315 test_on_seed(repeat("abc", copies), seed);
316
317 // Let's try truly random inputs of different lengths:
318 for (std::size_t length = 0; length != 200; ++length) {

Callers 1

test_equivalenceFunction · 0.85

Calls 6

sz_hash_state_equalFunction · 0.85
iterate_in_random_slicesFunction · 0.85
repeatFunction · 0.85
randomize_stringFunction · 0.85
dataMethod · 0.45
sizeMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…