48# include <gtest/gtest.h>
63# include <string_view>
64# include <unordered_set>
80 const char * name =
"";
81 size_t (* hash)(
const void *, size_t) =
nullptr;
82 bool is_strong =
false;
88 size_t add (
const void * p,
size_t len) {
return add_hash(p, len); }
89 size_t xor_ (
const void * p,
size_t len) {
return xor_hash(p, len); }
90 size_t rot (
const void * p,
size_t len) {
return rot_hash(p, len); }
91 size_t djb (
const void * p,
size_t len) {
return djb_hash(p, len); }
92 size_t sax (
const void * p,
size_t len) {
return sax_hash(p, len); }
93 size_t fnv (
const void * p,
size_t len) {
return fnv_hash(p, len); }
94 size_t oat (
const void * p,
size_t len) {
return oat_hash(p, len); }
95 size_t jsw (
const void * p,
size_t len) {
return jsw_hash(p, len); }
96 size_t elf (
const void * p,
size_t len) {
return elf_hash(p, len); }
97 size_t jen (
const void * p,
size_t len)
100 size_t murmur3(
const void * p,
size_t len)
101 {
return murmur3hash(std::string(
static_cast<const char *
>(p), len), 42u); }
103 size_t wyh (
const void * p,
size_t len) {
return wyhash_hash(p, len, 42); }
111 {
"murmur3hash", Wrap::murmur3,
true},
112 {
"xxhash64_hash", Wrap::xxh64,
true},
113 {
"wyhash_hash", Wrap::wyh,
true},
114 {
"siphash24_hash", Wrap::sip24,
true},
121 {
"SuperFastHash", Wrap::sfh,
false},
122 {
"fnv_hash", Wrap::fnv,
false},
123 {
"oat_hash", Wrap::oat,
false},
124 {
"djb_hash", Wrap::djb,
false},
133 {
"add_hash", Wrap::add,
false},
134 {
"xor_hash", Wrap::xor_,
false},
135 {
"rot_hash", Wrap::rot,
false},
136 {
"sax_hash", Wrap::sax,
false},
137 {
"jsw_hash", Wrap::jsw,
false},
138 {
"elf_hash", Wrap::elf,
false},
139 {
"jen_hash", Wrap::jen,
false},
154std::vector<std::string>
random_keys(
size_t n,
size_t len, std::uint64_t
seed)
157 std::uniform_int_distribution<int>
byte_dist(0, 255);
158 std::vector<std::string>
out;
160 for (
size_t i = 0; i < n; ++i)
162 std::string s(len,
'\0');
163 for (
size_t j = 0; j < len; ++j)
165 out.push_back(std::move(s));
172 const std::vector<std::string> &
keys)
175 for (
const auto &
k :
keys)
176 mask |=
fn.hash(
k.data(),
k.
size());
177 return std::max<size_t>(std::bit_width(mask), 1);
187 bool is_strong =
false;
188 bool is_weak =
false;
189 double sac_max_bias = 1.0;
190 double sac_avg_bias = 1.0;
191 double bic_max_corr = 1.0;
192 double diff_worst = 1.0;
193 double multireschi = 999.0;
194 double adv_chi_ctr = 999.0;
195 double adv_chi_pfx = 999.0;
196 bool align_ok =
false;
197 double score = 999.0;
208 return 3.0 *
m.sac_max_bias
209 + 2.0 *
m.sac_avg_bias
210 + 2.0 *
m.bic_max_corr
212 + 1.0 *
m.multireschi
213 + 0.5 *
m.adv_chi_ctr
214 + 0.5 *
m.adv_chi_pfx
222 static constexpr std::string_view
weak_names[] = {
223 "add_hash",
"xor_hash",
"rot_hash",
"sax_hash",
224 "jsw_hash",
"elf_hash",
"jen_hash"
229 rm.is_strong =
fn.is_strong;
231 [&](std::string_view
w){
return w ==
fn.name; });
233 constexpr size_t N_s = 4096;
234 constexpr size_t klen = 16;
242 std::vector<std::vector<size_t>> mat(
in_bits,
244 for (
const auto & base :
keys)
246 const size_t h0 =
fn.hash(base.data(), base.size());
247 for (
size_t i = 0; i <
in_bits; ++i)
249 std::string
mut = base;
250 mut[i / 8] ^=
static_cast<char>(1u << (i % 8));
252 for (
size_t j = 0; j <
out_bits; ++j)
253 mat[i][j] += (
diff >> j) & 1u;
257 for (
size_t i = 0; i <
in_bits; ++i)
258 for (
size_t j = 0; j <
out_bits; ++j)
260 const double p =
static_cast<double>(mat[i][j]) /
N_s;
261 const double bias = std::abs(p - 0.5);
271 std::mt19937_64
rng(0xB1C3);
273 constexpr size_t pairs = 64;
279 for (
size_t s = 0; s <
N_s; ++s)
283 mut[i / 8] ^=
static_cast<char>(1u << (i % 8));
286 for (
size_t p = 0; p < pairs; ++p)
292 for (
size_t s = 0; s <
N_s; ++s)
294 const double bj = (
diffs[s] >> j) & 1u;
295 const double bk = (
diffs[s] >>
k) & 1u;
299 const double n =
N_s;
300 const double num = n*
sjk -
sj*
sk;
310 std::mt19937_64
rng(0xD1FF3);
313 for (
size_t target : {1u, 4u, 16u})
316 for (
const auto & base :
keys)
318 std::string
mut = base;
319 std::vector<size_t> bits(
in_bits);
320 std::iota(bits.begin(), bits.end(), 0);
321 for (
size_t f = 0; f < target
and f < bits.size(); ++f)
323 std::uniform_int_distribution<size_t> dist(f, bits.size()-1);
324 std::swap(bits[f], bits[dist(
rng)]);
325 const size_t b = bits[f];
326 mut[b/8] ^=
static_cast<char>(1u << (b%8));
328 const size_t h0 =
fn.hash(base.data(), base.size());
329 const size_t h1 =
fn.hash(
mut.data(),
mut.size());
341 constexpr size_t N_chi = 50000;
343 const std::array<size_t, 4> buckets = {127, 1024, 4096, 8191};
345 for (
const size_t b : buckets)
347 std::vector<size_t> cnt(b, 0);
349 ++cnt[
fn.hash(
k.data(),
k.
size()) % b];
350 const double exp =
static_cast<double>(
N_chi) / b;
352 for (
const size_t c : cnt)
353 {
const double d = c -
exp;
chi += d*d/
exp; }
361 constexpr size_t N_adv = 65536;
362 constexpr size_t B_adv = 1024;
363 std::vector<size_t> cnt(
B_adv, 0);
364 for (
size_t i = 0; i <
N_adv; ++i)
365 { std::uint64_t v = i; cnt[
fn.hash(&v,
sizeof(v)) %
B_adv]++; }
368 for (
const size_t c : cnt) {
const double d = c -
exp;
chi += d*d/
exp; }
374 constexpr size_t N_adv = 65536;
375 constexpr size_t B_adv = 1024;
376 constexpr size_t pfxlen = 128;
378 std::vector<size_t> cnt(
B_adv, 0);
379 for (
size_t i = 0; i <
N_adv; ++i)
382 std::uint32_t s =
static_cast<std::uint32_t
>(i);
383 k.append(
reinterpret_cast<const char *
>(&s),
sizeof(s));
384 cnt[
fn.hash(
k.data(),
k.size()) %
B_adv]++;
388 for (
const size_t c : cnt) {
const double d = c -
exp;
chi += d*d/
exp; }
395 constexpr size_t pad = 16;
397 std::mt19937_64
rng2(0xA119ULL);
403 std::memmove(buf.data() +
off, buf.data(),
test_len);
405 {
rm.align_ok =
false;
break; }
406 std::memmove(buf.data(), buf.data() +
off,
test_len);
451 std::cout <<
"\n=== Strict Avalanche Criterion (SAC) ===\n"
453 <<
" Key length: " <<
key_len <<
" bytes\n\n";
466 for (
const auto & base :
keys)
468 const size_t h0 =
fn.hash(base.data(), base.size());
472 mutated[i / 8] ^=
static_cast<char>(1u << (i % 8));
475 for (
size_t j = 0; j <
out_bits; ++j)
489 for (
size_t j = 0; j <
out_bits; ++j)
491 const double p =
static_cast<double>(
sac_matrix[i][j])
493 const double bias = std::abs(p - 0.5);
505 std::cout << std::left << std::setw(16) <<
fn.name
506 <<
" out_bits=" << std::setw(3) <<
out_bits
507 <<
" max_bias=" << std::fixed << std::setprecision(4) <<
max_bias
513 <<
fn.name <<
" SAC max per-cell bias exceeds 0.10";
515 <<
fn.name <<
" SAC average bias exceeds 0.03";
517 <<
fn.name <<
" SAC worst row mean deviation exceeds 0.05";
540 std::cout <<
"\n=== Bit Independence Criterion (BIC) ===\n";
553 std::mt19937_64
rng(0xB1C2ULL);
571 mutated[i / 8] ^=
static_cast<char>(1u << (i % 8));
589 const double bj =
static_cast<double>((
diffs[s] >> j) & 1u);
590 const double bk =
static_cast<double>((
diffs[s] >>
k) & 1u);
597 const double n =
static_cast<double>(
N_samples);
603 const double corr = std::abs(num /
den);
613 std::cout << std::left << std::setw(16) <<
fn.name
614 <<
" max_corr=" << std::fixed << std::setprecision(4) <<
max_corr
619 <<
fn.name <<
" BIC max pairwise correlation exceeds 0.15";
621 <<
fn.name <<
" BIC average pairwise correlation exceeds 0.05";
640 std::cout <<
"\n=== Differential Uniformity ===\n";
650 std::cout << std::left << std::setw(16) <<
fn.name;
661 for (
const auto & base :
keys)
663 const size_t h0 =
fn.hash(base.data(), base.size());
671 std::uniform_int_distribution<size_t> dist(f,
all_bits.size() - 1);
672 const size_t pick = dist(
rng);
679 const double d =
static_cast<double>(std::popcount(
h0 ^
h1));
690 <<
" mean=" << std::fixed << std::setprecision(2) <<
mean
696 <<
fn.name <<
" differential mean off at input dist " <<
target_dist;
711 constexpr size_t N_keys = 100000;
715 {127, 256, 509, 1024, 2039, 4096, 8191, 16384};
717 std::cout <<
"\n=== Multi-Resolution Distribution ===\n"
718 << std::left << std::setw(16) <<
"hash";
720 std::cout << std::right << std::setw(8) << b;
726 std::cout << std::left << std::setw(16) <<
fn.name;
730 std::vector<size_t>
counts(buckets, 0);
731 for (
const auto &
k :
keys)
732 ++
counts[
fn.hash(
k.data(),
k.size()) % buckets];
736 for (
const size_t c :
counts)
741 const double reduced =
chi /
static_cast<double>(buckets - 1);
743 std::cout << std::right << std::fixed << std::setprecision(3)
749 <<
fn.name <<
" chi-square too high at " << buckets <<
" buckets";
770 std::cout <<
"\n=== Adversarial: all-zero keys of varying lengths ===\n";
777 std::unordered_set<size_t> hashes;
778 for (
size_t len = 1; len <= 256; ++len)
780 const std::string key(len,
'\0');
781 hashes.insert(
fn.hash(key.data(), key.size()));
784 const double uniqueness =
static_cast<double>(hashes.size()) / 256.0;
785 std::cout << std::left << std::setw(16) <<
fn.name
786 <<
" uniqueness=" << std::fixed << std::setprecision(4)
787 << uniqueness <<
" (" << hashes.size() <<
"/256)\n";
790 <<
fn.name <<
" too many collisions on zero-filled length-varying keys";
799 std::cout <<
"\n=== Adversarial: single-bit-set keys ===\n";
805 std::unordered_set<size_t> hashes;
808 std::string key(
key_len,
'\0');
809 key[
bit / 8] =
static_cast<char>(1u << (
bit % 8));
810 hashes.insert(
fn.hash(key.data(), key.size()));
813 const double uniqueness =
814 static_cast<double>(hashes.size()) /
total_bits;
815 std::cout << std::left << std::setw(16) <<
fn.name
816 <<
" uniqueness=" << std::fixed << std::setprecision(4)
817 << uniqueness <<
" (" << hashes.size() <<
"/" <<
total_bits <<
")\n";
820 <<
fn.name <<
" collisions on single-bit-set keys";
828 constexpr size_t N = 100000;
829 constexpr size_t buckets = 1024;
831 std::cout <<
"\n=== Adversarial: counter keys ===\n";
837 std::vector<size_t>
counts(buckets, 0);
838 for (
size_t i = 0; i <
N; ++i)
840 std::uint64_t val =
static_cast<std::uint64_t
>(i);
841 counts[
fn.hash(&val,
sizeof(val)) % buckets]++;
844 const double expected =
static_cast<double>(
N) / buckets;
846 for (
const size_t c :
counts)
853 std::cout << std::left << std::setw(16) <<
fn.name
854 <<
" chi=" << std::fixed << std::setprecision(3) <<
reduced
859 <<
fn.name <<
" poor distribution on sequential counter keys";
867 constexpr size_t N = 256;
869 std::cout <<
"\n=== Adversarial: differ only in high byte ===\n";
875 std::unordered_set<size_t> hashes;
876 for (
size_t v = 0; v <
N; ++v)
879 key[
key_len - 1] =
static_cast<char>(v);
880 hashes.insert(
fn.hash(key.data(), key.size()));
884 <<
fn.name <<
" collision on keys differing only in last byte";
892 constexpr size_t max_len = 512;
893 const std::string
cycle =
"ABCDEFGH";
895 std::cout <<
"\n=== Adversarial: cyclic pattern keys ===\n";
901 std::unordered_set<size_t> hashes;
902 for (
size_t len = 1; len <= max_len; ++len)
906 for (
size_t i = 0; i < len; ++i)
908 hashes.insert(
fn.hash(key.data(), key.size()));
911 const double uniqueness =
912 static_cast<double>(hashes.size()) / max_len;
913 std::cout << std::left << std::setw(16) <<
fn.name
914 <<
" uniqueness=" << std::fixed << std::setprecision(4)
915 << uniqueness <<
"\n";
918 <<
fn.name <<
" collisions on cyclic-pattern keys";
927 constexpr size_t N = 65536;
928 constexpr size_t buckets = 1024;
930 std::cout <<
"\n=== Adversarial: long common prefix ===\n";
938 std::vector<size_t>
counts(buckets, 0);
939 for (
size_t i = 0; i <
N; ++i)
942 std::uint32_t
suffix =
static_cast<std::uint32_t
>(i);
943 key.append(
reinterpret_cast<const char *
>(&
suffix),
sizeof(
suffix));
944 counts[
fn.hash(key.data(), key.size()) % buckets]++;
947 const double expected =
static_cast<double>(
N) / buckets;
949 for (
const size_t c :
counts)
956 std::cout << std::left << std::setw(16) <<
fn.name
957 <<
" chi=" << std::fixed << std::setprecision(3) <<
reduced
963 <<
" poor distribution on long-prefix adversarial keys";
978 constexpr size_t pad = 16;
982 std::mt19937_64
rng(0xA119EULL);
984 c =
static_cast<char>(
rng() & 0xff);
986 std::cout <<
"\n=== Alignment Sensitivity ===\n";
1010 std::cout << std::left << std::setw(16) <<
fn.name
1011 <<
" alignment-stable: " << (
all_match ?
"yes" :
"NO")
1015 <<
fn.name <<
" produces different hashes for different alignments";
1028 constexpr size_t N = 8192;
1029 constexpr size_t key_len = 16;
1033 std::cout <<
"\n=== Seed Independence ===\n";
1039 size_t (* hash)(
const void *, size_t, std::uint64_t);
1042 const std::array<SeededFn, 3>
seeded_fns = {{
1043 {
"xxhash64_hash", [](
const void * p,
size_t l, std::uint64_t s) ->
size_t
1045 {
"wyhash_hash", [](
const void * p,
size_t l, std::uint64_t s) ->
size_t
1047 {
"siphash24_hash", [](
const void * p,
size_t l, std::uint64_t s) ->
size_t
1051 const std::array<std::uint64_t, 4> seeds = {0, 1, 42, 0xffffffffffffffff};
1058 std::vector<std::vector<size_t>>
hash_vecs(seeds.size(),
1059 std::vector<size_t>(
N));
1060 for (
size_t si = 0;
si < seeds.size(); ++
si)
1061 for (
size_t ki = 0;
ki <
N; ++
ki)
1068 for (
size_t a = 0; a < seeds.size(); ++a)
1069 for (
size_t b = a + 1; b < seeds.size(); ++b)
1073 for (
size_t k = 0;
k <
N; ++
k)
1075 const double va =
static_cast<double>(
1077 const double vb =
static_cast<double>(
1085 const double n =
static_cast<double>(
N);
1093 std::cout << std::left << std::setw(16) <<
fn.name
1094 <<
" max_cross_seed_corr=" << std::fixed << std::setprecision(5)
1098 <<
fn.name <<
" seeds are correlated (|r| > 0.05)";
1115 std::cout <<
"\n=== Sparse Key Collisions ===\n";
1125 for (
size_t K : {1, 2, 3})
1127 std::unordered_set<size_t> hashes;
1128 size_t key_count = 0;
1134 std::string key(
key_len,
'\0');
1135 key[b0 / 8] |=
static_cast<char>(1u << (b0 % 8));
1136 hashes.insert(
fn.hash(key.data(), key.size()));
1143 for (
size_t b1 = b0 + 1; b1 <
total_bits; ++b1)
1145 std::string key(
key_len,
'\0');
1146 key[b0 / 8] |=
static_cast<char>(1u << (b0 % 8));
1147 key[b1 / 8] |=
static_cast<char>(1u << (b1 % 8));
1148 hashes.insert(
fn.hash(key.data(), key.size()));
1155 for (
size_t b1 = b0 + 1; b1 <
total_bits; ++b1)
1156 for (
size_t b2 = b1 + 1; b2 <
total_bits; ++b2)
1158 std::string key(
key_len,
'\0');
1159 key[b0 / 8] |=
static_cast<char>(1u << (b0 % 8));
1160 key[b1 / 8] |=
static_cast<char>(1u << (b1 % 8));
1161 key[b2 / 8] |=
static_cast<char>(1u << (b2 % 8));
1162 hashes.insert(
fn.hash(key.data(), key.size()));
1167 const double uniqueness =
1168 static_cast<double>(hashes.size()) / key_count;
1170 std::cout << std::left << std::setw(16) <<
fn.name
1172 <<
" keys=" << std::setw(6) << key_count
1173 <<
" uniq=" << std::fixed << std::setprecision(6)
1174 << uniqueness <<
"\n";
1178 if constexpr (
sizeof(size_t) >= 8)
1180 <<
fn.name <<
" sparse key collision at K=" << K;
1195 std::cout <<
"\n=== Permutation Distribution ===\n";
1198 std::string base =
"ABCDEF";
1199 std::sort(base.begin(), base.end());
1200 constexpr size_t buckets = 64;
1206 std::vector<size_t>
counts(buckets, 0);
1208 std::string
perm = base;
1215 while (std::next_permutation(
perm.begin(),
perm.end()));
1219 for (
const size_t c :
counts)
1227 std::unordered_set<size_t>
uniq;
1231 while (std::next_permutation(
perm.begin(),
perm.end()));
1233 std::cout << std::left << std::setw(16) <<
fn.name
1235 <<
" chi=" << std::fixed << std::setprecision(3) <<
reduced
1236 <<
" uniq=" <<
uniq.size() <<
"/" <<
n_perms <<
"\n";
1239 <<
fn.name <<
" collision among byte permutations";
1253 constexpr size_t key_len = 32;
1256 std::cout <<
"\n=== Sliding Window Test ===\n";
1263 std::unordered_set<size_t> hashes;
1265 for (
size_t pos = 0; pos <
positions; ++pos)
1267 std::string key(
key_len,
'\0');
1269 key[pos +
w] =
'\xff';
1270 hashes.insert(
fn.hash(key.data(), key.size()));
1273 const double uniqueness =
1274 static_cast<double>(hashes.size()) /
positions;
1276 std::cout << std::left << std::setw(16) <<
fn.name
1278 <<
" uniq=" << hashes.size()
1279 <<
" uniqueness=" << std::fixed << std::setprecision(4)
1280 << uniqueness <<
"\n";
1283 <<
fn.name <<
" collision in sliding window test";
1297 std::cout <<
"\n=== Length Extension Sensitivity ===\n";
1299 const std::string base =
"HashTestPayload";
1308 std::unordered_set<size_t> hashes;
1311 std::string key = base + std::string(
extra,
'\0');
1312 hashes.insert(
fn.hash(key.data(), key.size()));
1315 const bool is_weak =
1316 (std::string_view(
fn.name) ==
"add_hash" or
1317 std::string_view(
fn.name) ==
"xor_hash" or
1318 std::string_view(
fn.name) ==
"rot_hash" or
1319 std::string_view(
fn.name) ==
"sax_hash" or
1320 std::string_view(
fn.name) ==
"jsw_hash" or
1321 std::string_view(
fn.name) ==
"elf_hash" or
1322 std::string_view(
fn.name) ==
"jen_hash");
1324 std::cout << std::left << std::setw(16) <<
fn.name
1325 <<
" distinct=" << hashes.size() <<
"/16"
1326 << (is_weak ?
" [weak — not asserted]" :
"")
1331 <<
fn.name <<
" fails length-extension sensitivity";
1349 std::vector<RankMetrics>
results;
1355 [] (
const RankMetrics & a,
const RankMetrics & b)
1356 { return a.score < b.score; });
1361 <<
"╔══════════════════════════════════════════════════════════════════════════════╗\n"
1362 <<
"║ [HASH-007] Hash Function Quality Ranking ║\n"
1363 <<
"╠══════════════════════════════════════════════════════════════════════════════╣\n"
1364 <<
"║ Rank Name SAC-max SAC-avg BIC-max Diff-wst MR-chi Adv-ctr ║\n"
1365 <<
"║ (max) Adv-pfx ║\n"
1368 <<
"╠══════════════════════════════════════════════════════════════════════════════╣\n";
1370 for (
size_t i = 0; i <
results.size(); ++i)
1373 const char * tag =
m.is_strong ?
"[Strong]"
1374 :
m.is_weak ?
"[Weak] "
1377 <<
"║ " << std::setw(2) << i + 1
1378 <<
". " << std::left << std::setw(16) <<
m.name
1380 <<
" " << std::right << std::fixed << std::setprecision(4)
1381 << std::setw(7) <<
m.sac_max_bias
1382 <<
" " << std::setw(7) <<
m.sac_avg_bias
1383 <<
" " << std::setw(7) <<
m.bic_max_corr
1384 <<
" " << std::setw(8) <<
m.diff_worst
1385 <<
" " << std::setw(7) <<
m.multireschi
1386 <<
" " << std::setw(7) <<
m.adv_chi_ctr
1388 <<
"║ " << std::string(22,
' ')
1391 << std::setw(7) <<
m.adv_chi_pfx
1393 <<
"║ " << std::string(22,
' ')
1396 << (
m.align_ok ?
" align✓" :
" alignX")
1398 <<
"║ " << std::string(22,
' ')
1401 << std::setw(7) <<
m.score
1403 <<
"╠══════════════════════════════════════════════════════════════════════════════╣\n";
1407 <<
"╚══════════════════════════════════════════════════════════════════════════════╝\n"
1408 <<
"\nLower score = better quality. Strong-profile threshold: score < 1.0\n"
1409 <<
"Columns: SAC-max/avg = Strict Avalanche Criterion bias\n"
1410 <<
" BIC-max = Bit Independence max correlation\n"
1411 <<
" Diff-wst = worst differential mean deviation (relative)\n"
1412 <<
" MR-chi = max reduced chi-square across 4 table sizes\n"
1413 <<
" Adv-ctr/pfx = adversarial pattern chi-square\n"
1414 <<
"\n========================================\n"
1415 <<
"[HASH-007] Advanced validation complete.\n"
1416 <<
"========================================\n";
1420 double best_strong = std::numeric_limits<double>::max();
1421 double best_general = std::numeric_limits<double>::max();
1426 else if (
not m.is_weak)
1430 <<
"Best strong-profile function should outrank best general-profile function";
Simple dynamic array with automatic resizing and functional operations.
static void SetUpTestSuite()
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_exp_function > > exp(const __gmp_expr< T, U > &expr)
size_t sax_hash(const void *key, const size_t len) noexcept
Shift-Add-XOR hash (SAX hash)
size_t SuperFastHash(const void *key, size_t len, std::uint32_t seed=0) noexcept
Paul Hsieh super fast hash function.
size_t add_hash(const void *key, const size_t len) noexcept
Additive hash.
size_t jsw_hash(const void *key, size_t len) noexcept
JSW hash (Julienne Walker)
size_t xxhash64_hash(const void *key, size_t len, std::uint64_t seed) noexcept
xxHash64 from the xxHash family.
size_t djb_hash(const void *key, const size_t len) noexcept
Bernstein's hash (DJB hash)
size_t jen_hash(const void *key, size_t length, unsigned initval) noexcept
Jenkins hash (lookup3)
size_t xor_hash(const void *key, const size_t len) noexcept
XOR hash.
size_t fnv_hash(const void *key, const size_t len) noexcept
FNV-1a hash.
size_t siphash24_hash(const void *key, size_t len, std::uint64_t key0, std::uint64_t key1) noexcept
SipHash-2-4 keyed hash.
void init_jsw() noexcept
Initializes the randomized lookup table used by jsw_hash().
size_t rot_hash(const void *key, const size_t len) noexcept
Rotating hash.
size_t wyhash_hash(const void *key, size_t len, std::uint64_t seed) noexcept
wyhash non-cryptographic hash.
size_t elf_hash(const void *key, const size_t len) noexcept
ELF hash.
size_t oat_hash(const void *key, const size_t len) noexcept
One-at-a-Time hash (OAT hash)
TEST_F(HashValidation, StrictAvalancheCriterion)
const long double offset[]
Offset values indexed by symbol string length (bounded by MAX_OFFSET_INDEX)
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
size_t size(Node *root) noexcept
auto variance(const Container &data, bool population=false) -> std::decay_t< decltype(*std::begin(data))>
Compute variance using Welford's numerically stable algorithm.
static void suffix(Node *root, DynList< Node * > &acc)
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
static void prefix(Node *root, DynList< Node * > &acc)
auto stddev(const Container &data, bool population=false) -> std::decay_t< decltype(*std::begin(data))>
Compute standard deviation.
auto mean(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute the arithmetic mean.
bool diff(const C1 &c1, const C2 &c2, Eq e=Eq())
Check if two containers differ.
const unsigned Default_Hash_Seed
size_t murmur3hash(const Key &key, std::uint32_t seed)
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
Dynamic array container with automatic resizing.