datasketches-cpp
Loading...
Searching...
No Matches
HllSketchImplFactory.hpp
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#ifndef _HLLSKETCHIMPLFACTORY_HPP_
21#define _HLLSKETCHIMPLFACTORY_HPP_
22
23#include <stdexcept>
24
25#include "HllUtil.hpp"
26#include "HllSketchImpl.hpp"
27#include "CouponList.hpp"
28#include "CouponHashSet.hpp"
29#include "HllArray.hpp"
30#include "Hll4Array.hpp"
31#include "Hll6Array.hpp"
32#include "Hll8Array.hpp"
33
34namespace datasketches {
35
36template<typename A>
37class HllSketchImplFactory final {
38public:
39 static HllSketchImpl<A>* deserialize(std::istream& os, const A& allocator);
40 static HllSketchImpl<A>* deserialize(const void* bytes, size_t len, const A& allocator);
41
42 static CouponHashSet<A>* promoteListToSet(const CouponList<A>& list);
43 static HllArray<A>* promoteListOrSetToHll(const CouponList<A>& list);
44 static HllArray<A>* newHll(uint8_t lgConfigK, target_hll_type tgtHllType, const A& allocator);
45
46 // resets the input impl, deleting the input pointer and returning a new pointer
47 // full_size selects the state to reset to: an empty HLL array, or LIST (coupon) mode
48 static HllSketchImpl<A>* reset(HllSketchImpl<A>* impl, bool full_size);
49
50 static Hll4Array<A>* convertToHll4(const HllArray<A>& srcHllArr);
51 static Hll6Array<A>* convertToHll6(const HllArray<A>& srcHllArr);
52 static Hll8Array<A>* convertToHll8(const HllArray<A>& srcHllArr);
53};
54
55template<typename A>
56CouponHashSet<A>* HllSketchImplFactory<A>::promoteListToSet(const CouponList<A>& list) {
57 using ChsAlloc = typename std::allocator_traits<A>::template rebind_alloc<CouponHashSet<A>>;
58 CouponHashSet<A>* chSet = new (ChsAlloc(list.getAllocator()).allocate(1)) CouponHashSet<A>(list.getLgConfigK(), list.getTgtHllType(), list.getAllocator());
59 for (const auto coupon: list) {
60 chSet->couponUpdate(coupon);
61 }
62 return chSet;
63}
64
65template<typename A>
66HllArray<A>* HllSketchImplFactory<A>::promoteListOrSetToHll(const CouponList<A>& src) {
67 HllArray<A>* tgtHllArr = HllSketchImplFactory<A>::newHll(src.getLgConfigK(), src.getTgtHllType(), src.getAllocator());
68 tgtHllArr->putKxQ0(1 << src.getLgConfigK());
69 for (const auto coupon: src) {
70 tgtHllArr->couponUpdate(coupon);
71 }
72 tgtHllArr->putHipAccum(src.getEstimate());
73 tgtHllArr->putOutOfOrderFlag(false);
74 return tgtHllArr;
75}
76
77template<typename A>
78HllSketchImpl<A>* HllSketchImplFactory<A>::deserialize(std::istream& is, const A& allocator) {
79 // we'll hand off the sketch based on PreInts so we don't need
80 // to move the stream pointer back and forth -- perhaps somewhat fragile?
81 const uint8_t preInts = static_cast<uint8_t>(is.peek());
82 if (preInts == hll_constants::HLL_PREINTS) {
83 return HllArray<A>::newHll(is, allocator);
84 } else if (preInts == hll_constants::HASH_SET_PREINTS) {
85 return CouponHashSet<A>::newSet(is, allocator);
86 } else if (preInts == hll_constants::LIST_PREINTS) {
87 return CouponList<A>::newList(is, allocator);
88 } else {
89 throw std::invalid_argument("Attempt to deserialize unknown object type");
90 }
91}
92
93template<typename A>
94HllSketchImpl<A>* HllSketchImplFactory<A>::deserialize(const void* bytes, size_t len, const A& allocator) {
95 // read current mode directly
96 const uint8_t preInts = static_cast<const uint8_t*>(bytes)[0];
97 if (preInts == hll_constants::HLL_PREINTS) {
98 return HllArray<A>::newHll(bytes, len, allocator);
99 } else if (preInts == hll_constants::HASH_SET_PREINTS) {
100 return CouponHashSet<A>::newSet(bytes, len, allocator);
101 } else if (preInts == hll_constants::LIST_PREINTS) {
102 return CouponList<A>::newList(bytes, len, allocator);
103 } else {
104 throw std::invalid_argument("Attempt to deserialize unknown object type");
105 }
106}
107
108template<typename A>
109HllArray<A>* HllSketchImplFactory<A>::newHll(uint8_t lgConfigK, target_hll_type tgtHllType, const A& allocator) {
110 switch (tgtHllType) {
111 case HLL_8:
112 using Hll8Alloc = typename std::allocator_traits<A>::template rebind_alloc<Hll8Array<A>>;
113 return new (Hll8Alloc(allocator).allocate(1)) Hll8Array<A>(lgConfigK, allocator);
114 case HLL_6:
115 using Hll6Alloc = typename std::allocator_traits<A>::template rebind_alloc<Hll6Array<A>>;
116 return new (Hll6Alloc(allocator).allocate(1)) Hll6Array<A>(lgConfigK, allocator);
117 case HLL_4:
118 using Hll4Alloc = typename std::allocator_traits<A>::template rebind_alloc<Hll4Array<A>>;
119 return new (Hll4Alloc(allocator).allocate(1)) Hll4Array<A>(lgConfigK, allocator);
120 }
121 throw std::logic_error("Invalid target_hll_type");
122}
123
124template<typename A>
125HllSketchImpl<A>* HllSketchImplFactory<A>::reset(HllSketchImpl<A>* impl, bool full_size) {
126 if (full_size) {
127 HllArray<A>* hll = newHll(impl->getLgConfigK(), impl->getTgtHllType(), impl->getAllocator());
128 impl->get_deleter()(impl);
129 return hll;
130 } else {
131 using ClAlloc = typename std::allocator_traits<A>::template rebind_alloc<CouponList<A>>;
132 CouponList<A>* cl = new (ClAlloc(impl->getAllocator()).allocate(1)) CouponList<A>(impl->getLgConfigK(), impl->getTgtHllType(), hll_mode::LIST, impl->getAllocator());
133 impl->get_deleter()(impl);
134 return cl;
135 }
136}
137
138template<typename A>
139Hll4Array<A>* HllSketchImplFactory<A>::convertToHll4(const HllArray<A>& srcHllArr) {
140 using Hll4Alloc = typename std::allocator_traits<A>::template rebind_alloc<Hll4Array<A>>;
141 return new (Hll4Alloc(srcHllArr.getAllocator()).allocate(1)) Hll4Array<A>(srcHllArr);
142}
143
144template<typename A>
145Hll6Array<A>* HllSketchImplFactory<A>::convertToHll6(const HllArray<A>& srcHllArr) {
146 using Hll6Alloc = typename std::allocator_traits<A>::template rebind_alloc<Hll6Array<A>>;
147 return new (Hll6Alloc(srcHllArr.getAllocator()).allocate(1)) Hll6Array<A>(srcHllArr);
148}
149
150template<typename A>
151Hll8Array<A>* HllSketchImplFactory<A>::convertToHll8(const HllArray<A>& srcHllArr) {
152 using Hll8Alloc = typename std::allocator_traits<A>::template rebind_alloc<Hll8Array<A>>;
153 return new (Hll8Alloc(srcHllArr.getAllocator()).allocate(1)) Hll8Array<A>(srcHllArr);
154}
155
156}
157
158#endif /* _HLLSKETCHIMPLFACTORY_HPP_ */
DataSketches namespace.
Definition binomial_bounds.hpp:38
target_hll_type
Specifies the target type of HLL sketch to be created.
Definition hll.hpp:72
@ HLL_6
6 bits per entry (fixed size)
Definition hll.hpp:74
@ HLL_8
8 bits per entry (fastest, fixed size)
Definition hll.hpp:75
@ HLL_4
4 bits per entry (most compact, size may vary)
Definition hll.hpp:73