96 int n_keys_left, b_mask, a_shift;
101 b_mask = (1 << pm->
b_bits) - 1;
107 while (n_keys_left >= 2)
114 x0 += (
u32) k[0].key;
115 x1 += (
u32) k[1].key;
120 k[0].
b = z0 & b_mask;
121 k[1].
b = z1 & b_mask;
122 k[0].
a = z0 >> a_shift;
123 k[1].
a = z1 >> a_shift;
131 if (n_keys_left >= 1)
140 k[0].
b = z0 & b_mask;
141 k[0].
a = z0 >> a_shift;
152 int n_keys_left, b_mask, a_shift;
157 b_mask = (1 << pm->
b_bits) - 1;
163 while (n_keys_left >= 2)
170 x0 += (
u64) k[0].key;
171 x1 += (
u64) k[1].key;
176 k[0].
b = z0 & b_mask;
177 k[1].
b = z1 & b_mask;
178 k[0].
a = z0 >> a_shift;
179 k[1].
a = z1 >> a_shift;
187 if (n_keys_left >= 1)
196 k[0].
b = z0 & b_mask;
197 k[0].
a = z0 >> a_shift;
208 int n_keys_left, b_mask, a_shift;
213 b_mask = (1 << pm->
b_bits) - 1;
219 while (n_keys_left >= 2)
229 x0 += xyz[0]; y0 += xyz[1]; z0 += xyz[2];
230 x1 += xyz[3]; y1 += xyz[4]; z1 += xyz[5];
235 k[0].
b = z0 & b_mask;
236 k[1].
b = z1 & b_mask;
237 k[0].
a = z0 >> a_shift;
238 k[1].
a = z1 >> a_shift;
246 if (n_keys_left >= 1)
254 x0 += xyz[0]; y0 += xyz[1]; z0 += xyz[2];
258 k[0].
b = z0 & b_mask;
259 k[0].
a = z0 >> a_shift;
270 int n_keys_left, b_mask, a_shift;
275 b_mask = (1 << pm->
b_bits) - 1;
281 while (n_keys_left >= 2)
291 x0 += xyz[0]; y0 += xyz[1]; z0 += xyz[2];
292 x1 += xyz[3]; y1 += xyz[4]; z1 += xyz[5];
297 k[0].
b = z0 & b_mask;
298 k[1].
b = z1 & b_mask;
299 k[0].
a = z0 >> a_shift;
300 k[1].
a = z1 >> a_shift;
308 if (n_keys_left >= 1)
316 x0 += xyz[0]; y0 += xyz[1]; z0 += xyz[2];
320 k[0].
b = z0 & b_mask;
321 k[0].
a = z0 >> a_shift;
367 tb = pm->
tabb + k->
b;
369 for (i = 0; i <
vec_len (ki); i++)
371 l = pm->
keys + ki[
i];
387 return no_collisions;
396 u32 ki,
i, hash, child, parent;
403 for (child = tail - 1; child; child = parent)
405 q_child = &pm->
tabq[child];
407 q_parent = &pm->
tabq[parent];
422 if (ki == pm->
tabh[hash])
439 if (parent == 0)
continue;
441 else if (pm->
tabh[hash] != ~0)
494 for (q = 0; q < tail; q++)
503 for (v = 0; v < v_limit; v++)
509 ki = tb_parent->
keys[
i];
510 k_parent = pm->
keys + ki;
520 k_child = pm->
keys + ki;
521 tb_hit = pm->
tabb + k_child->
b;
526 if (tb_child == tb_hit)
533 if (tb_hit->
water_b == high_water)
542 tb_child->
water_b = high_water;
543 pm->
tabq[tail].
b_q = tb_child ? tb_child - pm->
tabb : ~0;
553 if (
apply (pm, tail, 0))
574 tb1 = sort_tabb + b1[0];
575 tb2 = sort_tabb + b2[0];
593 sort_tabb = pm->
tabb;
645 u32 s_bits, s_max, a_max, b_max, n_keys;
646 int is_minimal, is_fast_mode;
647 const u32 b_max_use_scramble_threshold = 4096;
664 case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
665 a_max = is_minimal ? s_max / 2 : s_max;
668 case 9:
case 10:
case 11:
case 12:
case 13:
669 case 14:
case 15:
case 16:
case 17:
675 else if (s_max/4 < b_max_use_scramble_threshold)
677 if (n_keys <= s_max*0.52)
678 a_max = b_max = s_max/8;
680 a_max = b_max = s_max/4;
684 a_max = ((n_keys <= s_max*(5.0/8.0)) ? s_max/8 :
685 (n_keys <= s_max*(3.0/4.0)) ? s_max/4 : s_max/2);
691 a_max = b_max = s_max/2;
695 b_max = (n_keys <= s_max*(5.0/8.0)) ? s_max/4 : s_max/2;
700 a_max = (n_keys <= s_max*(5.0/8.0)) ? s_max/8 : s_max/2;
701 b_max = (n_keys <= s_max*(5.0/8.0)) ? s_max/4 : s_max/2;
706 a_max = b_max = s_max/2;
713 if (is_fast_mode && n_keys > s_max*0.8)
719 if (s_max/4 <= (1 << 14))
720 b_max = ((n_keys <= s_max*0.56) ? s_max/32 :
721 (n_keys <= s_max*0.74) ? s_max/16 : s_max/8);
723 b_max = ((n_keys <= s_max*0.6) ? s_max/16 :
724 (n_keys <= s_max*0.8) ? s_max/8 : s_max/4);
726 if (is_fast_mode && b_max < s_max/8)
729 if (a_max < 1) a_max = 1;
730 if (b_max < 1) b_max = 1;
733 ASSERT (s_max == (1 << s_bits));
739 if (b_max >= b_max_use_scramble_threshold)
748 int mask = (1 << nbits) - 1;
749 int const2 = 1+nbits/2;
750 int const3 = 1+nbits/3;
751 int const4 = 1+nbits/4;
752 int const5 = 1+nbits/5;
753 for (i = 0; i < 20; i++)
755 x = (x + (x << const2)) & mask;
756 x = (x ^ (x >> const3));
757 x = (x + (x << const4)) & mask;
758 x = (x ^ (x >> const5));
779 u32 max_a_bits, n_tries_this_a_b, want_minimal;
790 max_a_bits = pm->
s_bits - want_minimal;
805 n_tries_this_a_b = 0;
828 if (n_tries_this_a_b < 2048)
832 if (pm->
a_bits < max_a_bits)
891 x0 += xyz[0]; y0 += xyz[1]; z0 += xyz[2];
911 x0 += xyz[0]; y0 += xyz[1]; z0 += xyz[2];
933 uword * unique_bitmap = 0;
952 unique_bitmap = clib_bitmap_ori (unique_bitmap, h);
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
static void init_keys_indirect_u32(phash_main_t *pm)
void(* key_seed1)(void *private, uword key, void *seed)
clib_error_t * phash_validate(phash_main_t *pm)
sll srl srl sll sra u16x4 i
#define PHASH_FLAG_FAST_MODE
#define clib_error(format, args...)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
static void guess_initial_parameters(phash_main_t *pm)
always_inline uword max_log2(uword x)
always_inline u32 scramble_permute(u32 x, u32 nbits)
#define vec_bytes(v)
Number of data bytes in vector.
static int phash_tabb_compare(void *a1, void *a2)
static void init_keys_direct_u32(phash_main_t *pm)
#define PHASH_FLAG_MINIMAL
clib_error_t * phash_find_perfect_hash(phash_main_t *pm)
int(* key_is_equal)(void *private, uword key1, uword key2)
static int augment(phash_main_t *pm, u32 b_root, u32 high_water)
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
void(* key_seed2)(void *private, uword key1, uword key2, void *seed)
static int init_tabb(phash_main_t *pm)
always_inline void phash_main_free_working_memory(phash_main_t *pm)
always_inline uword clib_bitmap_get(uword *ai, uword i)
static int perfect(phash_main_t *pm)
#define hash_mix64(a0, b0, c0)
#define vec_free(V)
Free vector's memory (no header).
#define hash_mix32(a0, b0, c0)
always_inline uword is_pow2(uword x)
always_inline u64 random_u64(u32 *seed)
64-bit random number generator
static int apply(phash_main_t *pm, u32 tail, u32 rollback)
#define clib_bitmap_free(v)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
static phash_tabb_t * sort_tabb
uword phash_hash_slow(phash_main_t *pm, uword key)
Linear Congruential Random Number Generator.
#define vec_foreach(var, vec)
Vector iterator.
static void init_keys_indirect_u64(phash_main_t *pm)
always_inline uword min_log2(uword x)
static void init_keys_direct_u64(phash_main_t *pm)
#define clib_error_return(e, args...)
always_inline void phash_tabb_free(phash_tabb_t *b)
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
static void scramble_init(phash_main_t *pm)
#define PHASH_FLAG_USE_SCRAMBLE