/** * Adds a new key to the set * @arg s The set to add to * @arg key The key to add */ void set_add(set_t *s, char *key) { uint32_t i; uint64_t out[2]; MurmurHash3_x64_128(key, strlen(key), 0, &out); switch (s->type) { case EXACT: // Check if this element is already added for (i=0; i < s->store.s.count; i++) { if (out[1] == s->store.s.hashes[i]) return; } // Check if we can fit this in the array if (i < SET_MAX_EXACT) { s->store.s.hashes[i] = out[1]; s->store.s.count++; return; } // Otherwise, force conversion to HLL // and purposely fall through to add the // element to the HLL convert_exact_to_approx(s); case APPROX: hll_add_hash(&s->store.h, out[1]); break; } }
/** * Adds a new key to the HLL * @arg h The hll to add to * @arg key The key to add */ void hll_add(hll_t *h, char *key) { // Compute the hash value of the key uint64_t out[2]; MurmurHash3_x64_128(key, strlen(key), 0, &out); // Add the hashed value hll_add_hash(h, out[1]); }
END_TEST START_TEST(test_hll_add_hash) { hll_t h; fail_unless(hll_init(10, &h) == 0); char buf[100]; for (uint64_t i=0; i < 100; i++) { hll_add_hash(&h, i ^ rand()); } fail_unless(hll_destroy(&h) == 0); }
/** * Converts a full exact set to an approximate HLL set. */ static void convert_exact_to_approx(set_t *s) { // Store the hashes, as HLL initialization // will step on the pointer uint64_t *hashes = s->store.s.hashes; // Initialize the HLL s->type = APPROX; hll_init(s->store.s.precision, &s->store.h); // Add each hash to the HLL for (int i=0; i < SET_MAX_EXACT; i++) { hll_add_hash(&s->store.h, hashes[i]); } // Free the array of hashes free(hashes); }