23#include "MurmurHash3.h"
24#include "RelativeErrorTables.hpp"
25#include "count_zeros.hpp"
26#include "common_defs.hpp"
27#include "ceiling_power_of_2.hpp"
35enum hll_mode { LIST = 0, SET, HLL };
37namespace hll_constants {
40static const uint8_t SER_VER = 1;
41static const uint8_t FAMILY_ID = 7;
43static const uint8_t EMPTY_FLAG_MASK = 4;
44static const uint8_t COMPACT_FLAG_MASK = 8;
45static const uint8_t OUT_OF_ORDER_FLAG_MASK = 16;
51static const uint8_t RESERVED_FLAG_MASK_32 = 32;
55static const uint8_t FULL_SIZE_FLAG_MASK = RESERVED_FLAG_MASK_32;
57static const uint32_t PREAMBLE_INTS_BYTE = 0;
58static const uint32_t SER_VER_BYTE = 1;
59static const uint32_t FAMILY_BYTE = 2;
60static const uint32_t LG_K_BYTE = 3;
61static const uint32_t LG_ARR_BYTE = 4;
62static const uint32_t FLAGS_BYTE = 5;
63static const uint32_t LIST_COUNT_BYTE = 6;
64static const uint32_t HLL_CUR_MIN_BYTE = 6;
65static const uint32_t MODE_BYTE = 7;
68static const uint32_t LIST_INT_ARR_START = 8;
69static const uint8_t LIST_PREINTS = 2;
71static const uint32_t HASH_SET_COUNT_INT = 8;
72static const uint32_t HASH_SET_INT_ARR_START = 12;
73static const uint8_t HASH_SET_PREINTS = 3;
75static const uint8_t HLL_PREINTS = 10;
76static const uint32_t HLL_BYTE_ARR_START = 40;
77static const uint32_t HIP_ACCUM_DOUBLE = 8;
78static const uint32_t KXQ0_DOUBLE = 16;
79static const uint32_t KXQ1_DOUBLE = 24;
80static const uint32_t CUR_MIN_COUNT_INT = 32;
81static const uint32_t AUX_COUNT_INT = 36;
83static const uint32_t EMPTY_SKETCH_SIZE_BYTES = 8;
86static const uint8_t KEY_BITS_26 = 26;
87static const uint8_t VAL_BITS_6 = 6;
88static const uint32_t KEY_MASK_26 = (1 << KEY_BITS_26) - 1;
89static const uint32_t VAL_MASK_6 = (1 << VAL_BITS_6) - 1;
90static const uint32_t EMPTY = 0;
91static const uint8_t MIN_LOG_K = 4;
92static const uint8_t MAX_LOG_K = 21;
94static const double HLL_HIP_RSE_FACTOR = 0.8325546111576977;
95static const double HLL_NON_HIP_RSE_FACTOR = 1.0389617614136892;
96static const double COUPON_RSE_FACTOR = 0.409;
97static const double COUPON_RSE = COUPON_RSE_FACTOR / (1 << 13);
99static const uint8_t LG_INIT_LIST_SIZE = 3;
100static const uint8_t LG_INIT_SET_SIZE = 5;
101static const uint32_t RESIZE_NUMER = 3;
102static const uint32_t RESIZE_DENOM = 4;
104static const uint8_t loNibbleMask = 0x0f;
105static const uint8_t hiNibbleMask = 0xf0;
106static const uint8_t AUX_TOKEN = 0xf;
112static const uint8_t LG_AUX_ARR_INTS[] = {
113 0, 2, 2, 2, 2, 2, 2, 3, 3, 3,
114 4, 4, 5, 5, 6, 7, 8, 9, 10, 11,
115 12, 13, 14, 15, 16, 17, 18
123template<
typename A = std::allocator<u
int8_t> >
127 static uint32_t coupon(
const uint64_t hash[]);
128 static uint32_t coupon(
const HashState& hashState);
129 static void hash(
const void* key,
size_t keyLen, uint64_t seed, HashState& result);
130 static uint8_t checkLgK(uint8_t lgK);
131 static void checkMemSize(uint64_t minBytes, uint64_t capBytes);
132 static inline void checkNumStdDev(uint8_t numStdDev);
133 static uint32_t pair(uint32_t slotNo, uint8_t value);
134 static uint32_t getLow26(uint32_t coupon);
135 static uint8_t getValue(uint32_t coupon);
136 static uint8_t simpleIntLog2(uint32_t n);
137 static uint8_t computeLgArrInts(hll_mode mode, uint32_t count, uint8_t lgConfigK);
138 static double getRelErr(
bool upperBound,
bool unioned, uint8_t lgConfigK, uint8_t numStdDev);
142inline uint32_t HllUtil<A>::coupon(
const uint64_t hash[]) {
143 uint32_t addr26 = hash[0] & hll_constants::KEY_MASK_26;
144 uint8_t lz = count_leading_zeros_in_u64(hash[1]);
145 uint8_t value = ((lz > 62 ? 62 : lz) + 1);
146 return (value << hll_constants::KEY_BITS_26) | addr26;
150inline uint32_t HllUtil<A>::coupon(
const HashState& hashState) {
151 uint32_t addr26 = (int) (hashState.h1 & hll_constants::KEY_MASK_26);
152 uint8_t lz = count_leading_zeros_in_u64(hashState.h2);
153 uint8_t value = ((lz > 62 ? 62 : lz) + 1);
154 return (value << hll_constants::KEY_BITS_26) | addr26;
158inline void HllUtil<A>::hash(
const void* key,
size_t keyLen, uint64_t seed, HashState& result) {
159 MurmurHash3_x64_128(key, keyLen, seed, result);
163inline uint8_t HllUtil<A>::checkLgK(uint8_t lgK) {
164 if ((lgK >= hll_constants::MIN_LOG_K) && (lgK <= hll_constants::MAX_LOG_K)) {
167 throw std::invalid_argument(
"Invalid value of k: " + std::to_string(lgK));
172inline double HllUtil<A>::getRelErr(
bool upperBound,
bool unioned,
173 uint8_t lgConfigK, uint8_t numStdDev) {
175 if (lgConfigK > 12) {
176 const double rseFactor = unioned ?
177 hll_constants::HLL_NON_HIP_RSE_FACTOR : hll_constants::HLL_HIP_RSE_FACTOR;
178 const uint32_t configK = 1 << lgConfigK;
179 return (upperBound ? -1 : 1) * (numStdDev * rseFactor) / sqrt(configK);
181 return RelativeErrorTables<A>::getRelErr(upperBound, unioned, lgConfigK, numStdDev);
186inline void HllUtil<A>::checkMemSize(uint64_t minBytes, uint64_t capBytes) {
187 if (capBytes < minBytes) {
188 throw std::invalid_argument(
"Given destination array is not large enough: " + std::to_string(capBytes));
193inline void HllUtil<A>::checkNumStdDev(uint8_t numStdDev) {
194 if ((numStdDev < 1) || (numStdDev > 3)) {
195 throw std::invalid_argument(
"NumStdDev may not be less than 1 or greater than 3.");
200inline uint32_t HllUtil<A>::pair(uint32_t slotNo, uint8_t value) {
201 return (value << hll_constants::KEY_BITS_26) | (slotNo & hll_constants::KEY_MASK_26);
205inline uint32_t HllUtil<A>::getLow26(uint32_t coupon) {
206 return coupon & hll_constants::KEY_MASK_26;
210inline uint8_t HllUtil<A>::getValue(uint32_t coupon) {
211 return coupon >> hll_constants::KEY_BITS_26;
215inline uint8_t HllUtil<A>::simpleIntLog2(uint32_t n) {
217 throw std::logic_error(
"cannot take log of 0");
219 return count_trailing_zeros_in_u32(n);
223inline uint8_t HllUtil<A>::computeLgArrInts(hll_mode mode, uint32_t count, uint8_t lgConfigK) {
225 if (mode == LIST) {
return hll_constants::LG_INIT_LIST_SIZE; }
226 uint32_t ceilPwr2 = ceiling_power_of_2(count);
227 if ((hll_constants::RESIZE_DENOM * count) > (hll_constants::RESIZE_NUMER * ceilPwr2)) { ceilPwr2 <<= 1;}
229 return std::max(hll_constants::LG_INIT_SET_SIZE, HllUtil<A>::simpleIntLog2(ceilPwr2));
232 return std::max(hll_constants::LG_AUX_ARR_INTS[lgConfigK], HllUtil<A>::simpleIntLog2(ceilPwr2));
DataSketches namespace.
Definition binomial_bounds.hpp:38