hyperloglog.h 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. #pragma once
  2. #include <util/system/types.h>
  3. #include <util/stream/input.h>
  4. #include <util/generic/array_ref.h>
  5. #include <vector>
  6. class IOutputStream;
  7. class THyperLogLogBase {
  8. protected:
  9. explicit THyperLogLogBase(unsigned precision);
  10. public:
  11. static const constexpr unsigned PRECISION_MIN = 4;
  12. static const constexpr unsigned PRECISION_MAX = 18;
  13. void Update(ui64 hash);
  14. void Merge(const THyperLogLogBase& rh);
  15. ui64 Estimate() const;
  16. void Save(IOutputStream& out) const;
  17. protected:
  18. unsigned Precision;
  19. TArrayRef<ui8> RegistersRef;
  20. };
  21. template <typename Alloc>
  22. class THyperLogLogWithAlloc : public THyperLogLogBase {
  23. private:
  24. explicit THyperLogLogWithAlloc(unsigned precision)
  25. : THyperLogLogBase(precision) {
  26. Registers.resize(1u << precision);
  27. RegistersRef = MakeArrayRef(Registers);
  28. }
  29. public:
  30. THyperLogLogWithAlloc(THyperLogLogWithAlloc&&) = default;
  31. THyperLogLogWithAlloc& operator=(THyperLogLogWithAlloc&&) = default;
  32. static THyperLogLogWithAlloc Create(unsigned precision) {
  33. return THyperLogLogWithAlloc(precision);
  34. }
  35. static THyperLogLogWithAlloc Load(IInputStream& in) {
  36. char precision = {};
  37. Y_ENSURE(in.ReadChar(precision));
  38. auto res = Create(precision);
  39. in.LoadOrFail(res.Registers.data(), res.Registers.size() * sizeof(res.Registers.front()));
  40. return res;
  41. }
  42. private:
  43. std::vector<ui8, Alloc> Registers;
  44. };
  45. using THyperLogLog = THyperLogLogWithAlloc<std::allocator<ui8>>;