datasketches 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/ext/datasketches/theta_wrapper.cpp +1 -1
- data/lib/datasketches/version.rb +1 -1
- data/vendor/datasketches-cpp/CMakeLists.txt +5 -3
- data/vendor/datasketches-cpp/CODE_OF_CONDUCT.md +1 -1
- data/vendor/datasketches-cpp/LICENSE +14 -0
- data/vendor/datasketches-cpp/README.md +67 -73
- data/vendor/datasketches-cpp/benchmarks/CMakeLists.txt +52 -0
- data/vendor/datasketches-cpp/benchmarks/benchmark_count_min_sketch.cpp +153 -0
- data/vendor/datasketches-cpp/benchmarks/benchmark_count_min_sketch_serialization.cpp +161 -0
- data/vendor/datasketches-cpp/common/CMakeLists.txt +1 -0
- data/vendor/datasketches-cpp/common/include/binomial_bounds.hpp +2 -2
- data/vendor/datasketches-cpp/common/include/fdlibm_log.hpp +101 -0
- data/vendor/datasketches-cpp/common/include/serde.hpp +6 -0
- data/vendor/datasketches-cpp/common/test/CMakeLists.txt +44 -2
- data/vendor/datasketches-cpp/common/test/binomial_bounds_test.cpp +279 -0
- data/vendor/datasketches-cpp/common/test/deserialize_hardening_test.cpp +188 -0
- data/vendor/datasketches-cpp/count/include/count_min.hpp +17 -4
- data/vendor/datasketches-cpp/count/include/count_min_impl.hpp +65 -83
- data/vendor/datasketches-cpp/count/test/count_min_test.cpp +63 -7
- data/vendor/datasketches-cpp/cpc/include/compression_data.hpp +2 -0
- data/vendor/datasketches-cpp/cpc/include/cpc_compressor_impl.hpp +16 -7
- data/vendor/datasketches-cpp/cpc/include/cpc_sketch.hpp +1 -0
- data/vendor/datasketches-cpp/cpc/include/cpc_sketch_impl.hpp +54 -36
- data/vendor/datasketches-cpp/cpc/include/cpc_union_impl.hpp +27 -27
- data/vendor/datasketches-cpp/cpc/include/cpc_util.hpp +7 -7
- data/vendor/datasketches-cpp/cpc/include/icon_estimator.hpp +5 -5
- data/vendor/datasketches-cpp/cpc/include/u32_table_impl.hpp +16 -16
- data/vendor/datasketches-cpp/cpc/test/cpc_sketch_test.cpp +35 -0
- data/vendor/datasketches-cpp/fi/include/frequent_items_sketch.hpp +28 -3
- data/vendor/datasketches-cpp/fi/include/frequent_items_sketch_impl.hpp +41 -25
- data/vendor/datasketches-cpp/fi/include/reverse_purge_hash_map.hpp +3 -1
- data/vendor/datasketches-cpp/fi/include/reverse_purge_hash_map_impl.hpp +10 -5
- data/vendor/datasketches-cpp/fi/test/frequent_items_sketch_serialize_for_java.cpp +24 -0
- data/vendor/datasketches-cpp/fi/test/frequent_items_sketch_test.cpp +116 -0
- data/vendor/datasketches-cpp/filters/include/bloom_filter.hpp +1 -1
- data/vendor/datasketches-cpp/filters/include/bloom_filter_impl.hpp +32 -12
- data/vendor/datasketches-cpp/filters/test/bloom_filter_test.cpp +28 -1
- data/vendor/datasketches-cpp/hll/include/CouponHashSet-internal.hpp +1 -2
- data/vendor/datasketches-cpp/hll/include/CouponList-internal.hpp +19 -5
- data/vendor/datasketches-cpp/hll/include/CubicInterpolation-internal.hpp +4 -4
- data/vendor/datasketches-cpp/hll/include/HarmonicNumbers-internal.hpp +2 -1
- data/vendor/datasketches-cpp/hll/include/Hll4Array-internal.hpp +4 -4
- data/vendor/datasketches-cpp/hll/include/Hll4Array.hpp +1 -1
- data/vendor/datasketches-cpp/hll/include/Hll6Array-internal.hpp +3 -3
- data/vendor/datasketches-cpp/hll/include/Hll6Array.hpp +1 -1
- data/vendor/datasketches-cpp/hll/include/Hll8Array-internal.hpp +6 -3
- data/vendor/datasketches-cpp/hll/include/Hll8Array.hpp +1 -1
- data/vendor/datasketches-cpp/hll/include/HllArray-internal.hpp +35 -29
- data/vendor/datasketches-cpp/hll/include/HllArray.hpp +1 -1
- data/vendor/datasketches-cpp/hll/include/HllSketch-internal.hpp +3 -5
- data/vendor/datasketches-cpp/hll/include/HllSketchImpl-internal.hpp +5 -11
- data/vendor/datasketches-cpp/hll/include/HllSketchImpl.hpp +2 -4
- data/vendor/datasketches-cpp/hll/include/HllSketchImplFactory.hpp +11 -10
- data/vendor/datasketches-cpp/hll/include/HllUnion-internal.hpp +17 -8
- data/vendor/datasketches-cpp/hll/include/HllUtil.hpp +12 -3
- data/vendor/datasketches-cpp/hll/include/coupon_iterator-internal.hpp +2 -2
- data/vendor/datasketches-cpp/hll/include/coupon_iterator.hpp +3 -0
- data/vendor/datasketches-cpp/hll/include/hll.hpp +11 -4
- data/vendor/datasketches-cpp/hll/include/hll.private.hpp +19 -0
- data/vendor/datasketches-cpp/hll/test/CMakeLists.txt +2 -0
- data/vendor/datasketches-cpp/hll/test/CouponListTest.cpp +64 -0
- data/vendor/datasketches-cpp/hll/test/HllFullSizeTest.cpp +137 -0
- data/vendor/datasketches-cpp/hll/test/HllKxqRebuildTest.cpp +150 -0
- data/vendor/datasketches-cpp/hll/test/HllSketchTest.cpp +3 -3
- data/vendor/datasketches-cpp/hll/test/HllUnionTest.cpp +71 -1
- data/vendor/datasketches-cpp/kll/include/kll_helper_impl.hpp +10 -10
- data/vendor/datasketches-cpp/kll/include/kll_sketch.hpp +10 -1
- data/vendor/datasketches-cpp/kll/include/kll_sketch_impl.hpp +33 -24
- data/vendor/datasketches-cpp/kll/test/kll_sketch_deserialize_from_java_test.cpp +24 -0
- data/vendor/datasketches-cpp/kll/test/kll_sketch_serialize_for_java.cpp +10 -0
- data/vendor/datasketches-cpp/quantiles/include/quantiles_sketch.hpp +11 -2
- data/vendor/datasketches-cpp/quantiles/include/quantiles_sketch_impl.hpp +24 -15
- data/vendor/datasketches-cpp/req/include/req_sketch.hpp +9 -0
- data/vendor/datasketches-cpp/req/include/req_sketch_impl.hpp +24 -15
- data/vendor/datasketches-cpp/req/test/req_sketch_deserialize_from_java_test.cpp +46 -0
- data/vendor/datasketches-cpp/req/test/req_sketch_serialize_for_java.cpp +20 -0
- data/vendor/datasketches-cpp/req/test/req_sketch_test.cpp +70 -0
- data/vendor/datasketches-cpp/sampling/include/ebpps_sample_impl.hpp +17 -8
- data/vendor/datasketches-cpp/sampling/include/ebpps_sketch.hpp +13 -0
- data/vendor/datasketches-cpp/sampling/include/var_opt_sketch.hpp +10 -1
- data/vendor/datasketches-cpp/sampling/include/var_opt_sketch_impl.hpp +6 -7
- data/vendor/datasketches-cpp/sampling/include/var_opt_union.hpp +5 -1
- data/vendor/datasketches-cpp/sampling/include/var_opt_union_impl.hpp +2 -1
- data/vendor/datasketches-cpp/sampling/test/ebpps_allocation_test.cpp +1 -1
- data/vendor/datasketches-cpp/sampling/test/ebpps_sketch_test.cpp +2 -2
- data/vendor/datasketches-cpp/sampling/test/var_opt_allocation_test.cpp +1 -1
- data/vendor/datasketches-cpp/sampling/test/var_opt_sketch_test.cpp +10 -4
- data/vendor/datasketches-cpp/sampling/test/var_opt_union_test.cpp +12 -0
- data/vendor/datasketches-cpp/tdigest/include/tdigest.hpp +38 -2
- data/vendor/datasketches-cpp/tdigest/include/tdigest_impl.hpp +168 -9
- data/vendor/datasketches-cpp/tdigest/test/CMakeLists.txt +1 -0
- data/vendor/datasketches-cpp/tdigest/test/tdigest_iterator_test.cpp +274 -0
- data/vendor/datasketches-cpp/tdigest/test/tdigest_test.cpp +275 -0
- data/vendor/datasketches-cpp/theta/include/compact_theta_sketch_parser.hpp +2 -0
- data/vendor/datasketches-cpp/theta/include/compact_theta_sketch_parser_impl.hpp +24 -3
- data/vendor/datasketches-cpp/theta/include/theta_constants.hpp +4 -2
- data/vendor/datasketches-cpp/theta/include/theta_helpers.hpp +32 -0
- data/vendor/datasketches-cpp/theta/include/theta_set_difference_base_impl.hpp +4 -2
- data/vendor/datasketches-cpp/theta/include/theta_sketch.hpp +22 -4
- data/vendor/datasketches-cpp/theta/include/theta_sketch_impl.hpp +60 -38
- data/vendor/datasketches-cpp/theta/include/theta_union_base_impl.hpp +2 -6
- data/vendor/datasketches-cpp/theta/include/theta_update_sketch_base_impl.hpp +2 -2
- data/vendor/datasketches-cpp/theta/test/bit_packing_test.cpp +50 -0
- data/vendor/datasketches-cpp/theta/test/theta_a_not_b_test.cpp +22 -0
- data/vendor/datasketches-cpp/theta/test/theta_sketch_test.cpp +315 -0
- data/vendor/datasketches-cpp/tools/rat-check.sh +68 -0
- data/vendor/datasketches-cpp/tuple/include/array_tuple_sketch.hpp +35 -4
- data/vendor/datasketches-cpp/tuple/include/array_tuple_sketch_impl.hpp +2 -2
- data/vendor/datasketches-cpp/tuple/include/tuple_sketch.hpp +41 -0
- data/vendor/datasketches-cpp/tuple/include/tuple_sketch_impl.hpp +5 -4
- data/vendor/datasketches-cpp/tuple/test/tuple_sketch_test.cpp +59 -0
- data/vendor/datasketches-cpp/version.cfg.in +1 -1
- metadata +12 -2
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// fdlibm __ieee754_log, used by Java's StrictMath.log (and by Math.log on most JVMs).
|
|
2
|
+
// Derived from FDLIBM 5.3, Copyright (C) 1993 by Sun Microsystems, Inc.
|
|
3
|
+
// "Permission to use, copy, modify, and distribute this software is freely granted,
|
|
4
|
+
// provided that this notice is preserved."
|
|
5
|
+
#ifndef FDLIBM_LOG_HPP
|
|
6
|
+
#define FDLIBM_LOG_HPP
|
|
7
|
+
#include <cstdint>
|
|
8
|
+
#include <cstring>
|
|
9
|
+
#include <limits>
|
|
10
|
+
|
|
11
|
+
namespace fdlibm {
|
|
12
|
+
|
|
13
|
+
inline int32_t hi_word(double x){ uint64_t u; std::memcpy(&u,&x,8); return (int32_t)(uint32_t)(u>>32); }
|
|
14
|
+
inline uint32_t lo_word(double x){ uint64_t u; std::memcpy(&u,&x,8); return (uint32_t)u; }
|
|
15
|
+
inline void set_hi_word(double& x, uint32_t hi){ uint64_t u; std::memcpy(&u,&x,8);
|
|
16
|
+
u = (u & 0x00000000ffffffffULL) | ((uint64_t)hi<<32); std::memcpy(&x,&u,8); }
|
|
17
|
+
|
|
18
|
+
// Forces a value to be rounded to a double before it is used again. fdlibm needs strict
|
|
19
|
+
// IEEE-754 evaluation: a fused multiply-add anywhere in the polynomial below changes the
|
|
20
|
+
// result. Pragmas are overridden by an explicit -ffp-contract=fast, so use a volatile
|
|
21
|
+
// round-trip, which the standard requires the compiler to honour.
|
|
22
|
+
inline double rnd(double v) { volatile double t = v; return t; }
|
|
23
|
+
|
|
24
|
+
inline double log(double x) {
|
|
25
|
+
// fdlibm depends on strict IEEE-754 evaluation: a fused multiply-add would change the result
|
|
26
|
+
// of the polynomial evaluation below, so contraction must be off for this function.
|
|
27
|
+
#if defined(__clang__)
|
|
28
|
+
#pragma clang fp contract(off)
|
|
29
|
+
#endif
|
|
30
|
+
static const double
|
|
31
|
+
ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
|
|
32
|
+
ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
|
|
33
|
+
two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
|
|
34
|
+
Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
|
|
35
|
+
Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
|
|
36
|
+
Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
|
|
37
|
+
Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
|
|
38
|
+
Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
|
|
39
|
+
Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
|
|
40
|
+
Lg7 = 1.479819860511658591e-01, /* 3FC2F112 DF3E5244 */
|
|
41
|
+
zero = 0.0;
|
|
42
|
+
|
|
43
|
+
double hfsq,f,s,z,R,w,t1,t2,dk;
|
|
44
|
+
int32_t k,hx,i,j;
|
|
45
|
+
uint32_t lx;
|
|
46
|
+
|
|
47
|
+
hx = hi_word(x);
|
|
48
|
+
lx = lo_word(x);
|
|
49
|
+
|
|
50
|
+
k = 0;
|
|
51
|
+
if (hx < 0x00100000) { /* x < 2**-1022 */
|
|
52
|
+
// fdlibm writes these as -two54/zero and (x-x)/zero, which also raise the divide-by-zero
|
|
53
|
+
// and invalid flags. MSVC rejects a compile-time division by a zero constant (C2124), so
|
|
54
|
+
// return the same values directly. The estimators never call log() with these inputs.
|
|
55
|
+
if (((hx & 0x7fffffff) | lx) == 0) { /* log(+-0) = -inf */
|
|
56
|
+
return -std::numeric_limits<double>::infinity();
|
|
57
|
+
}
|
|
58
|
+
if (hx < 0) { /* log(-#) = NaN */
|
|
59
|
+
return std::numeric_limits<double>::quiet_NaN();
|
|
60
|
+
}
|
|
61
|
+
k -= 54; x *= two54; /* subnormal: scale up */
|
|
62
|
+
hx = hi_word(x);
|
|
63
|
+
}
|
|
64
|
+
if (hx >= 0x7ff00000) { return x+x; }
|
|
65
|
+
k += (hx>>20) - 1023;
|
|
66
|
+
hx &= 0x000fffff;
|
|
67
|
+
i = (hx + 0x95f64) & 0x100000;
|
|
68
|
+
set_hi_word(x, (uint32_t)(hx | (i ^ 0x3ff00000))); /* normalize x or x/2 */
|
|
69
|
+
k += (i>>20);
|
|
70
|
+
f = x - 1.0;
|
|
71
|
+
if ((0x000fffff & (2+hx)) < 3) { /* |f| < 2**-20 */
|
|
72
|
+
if (f == zero) {
|
|
73
|
+
if (k == 0) { return zero; }
|
|
74
|
+
dk = (double)k; return rnd(dk*ln2_hi) + rnd(dk*ln2_lo);
|
|
75
|
+
}
|
|
76
|
+
R = rnd(rnd(f*f)*rnd(0.5 - rnd(0.33333333333333333*f)));
|
|
77
|
+
if (k == 0) { return f-R; }
|
|
78
|
+
dk = (double)k; return rnd(dk*ln2_hi) - (rnd(R - rnd(dk*ln2_lo)) - f);
|
|
79
|
+
}
|
|
80
|
+
s = f/(2.0+f);
|
|
81
|
+
dk = (double)k;
|
|
82
|
+
z = s*s;
|
|
83
|
+
i = hx - 0x6147a;
|
|
84
|
+
w = z*z;
|
|
85
|
+
j = 0x6b851 - hx;
|
|
86
|
+
t1 = rnd(w*rnd(Lg2 + rnd(w*rnd(Lg4 + rnd(w*Lg6)))));
|
|
87
|
+
t2 = rnd(z*rnd(Lg1 + rnd(w*rnd(Lg3 + rnd(w*rnd(Lg5 + rnd(w*Lg7)))))));
|
|
88
|
+
i |= j;
|
|
89
|
+
R = t2 + t1;
|
|
90
|
+
if (i > 0) {
|
|
91
|
+
hfsq = rnd(0.5*f)*f;
|
|
92
|
+
if (k == 0) { return f - rnd(hfsq - rnd(s*(hfsq+R))); }
|
|
93
|
+
return rnd(dk*ln2_hi) - (rnd(hfsq - rnd(rnd(s*(hfsq+R)) + rnd(dk*ln2_lo))) - f);
|
|
94
|
+
} else {
|
|
95
|
+
if (k == 0) { return f - rnd(s*(f-R)); }
|
|
96
|
+
return rnd(dk*ln2_hi) - (rnd(rnd(s*(f-R)) - rnd(dk*ln2_lo)) - f);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
} // namespace fdlibm
|
|
101
|
+
#endif
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
#ifndef DATASKETCHES_SERDE_HPP_
|
|
21
21
|
#define DATASKETCHES_SERDE_HPP_
|
|
22
22
|
|
|
23
|
+
#include <cstdint>
|
|
23
24
|
#include <cstring>
|
|
24
25
|
#include <iostream>
|
|
25
26
|
#include <memory>
|
|
@@ -132,6 +133,11 @@ struct serde<T, typename std::enable_if<std::is_arithmetic<T>::value>::type> {
|
|
|
132
133
|
/// ItemsSketch<String> with ArrayOfStringsSerDe in Java.
|
|
133
134
|
/// The length of each string is stored as a 32-bit integer (historically),
|
|
134
135
|
/// which may be too wasteful. Treat this as an example.
|
|
136
|
+
///
|
|
137
|
+
/// This implementation treats std::string as an arbitrary byte container.
|
|
138
|
+
/// It does not check whether string contents are valid UTF-8.
|
|
139
|
+
///
|
|
140
|
+
/// Use a UTF-8-validating SerDe when cross-language portability is required.
|
|
135
141
|
template<>
|
|
136
142
|
struct serde<std::string> {
|
|
137
143
|
/// @copydoc serde::serialize
|
|
@@ -69,15 +69,21 @@ target_sources(common_test
|
|
|
69
69
|
PRIVATE
|
|
70
70
|
quantiles_sorted_view_test.cpp
|
|
71
71
|
optional_test.cpp
|
|
72
|
+
binomial_bounds_test.cpp
|
|
72
73
|
)
|
|
73
74
|
|
|
74
75
|
# now the integration test part
|
|
75
76
|
add_executable(integration_test)
|
|
76
77
|
|
|
77
|
-
target_link_libraries(integration_test count cpc density fi hll kll req sampling theta tuple common_test_lib)
|
|
78
|
+
target_link_libraries(integration_test count cpc density fi hll kll req sampling theta tuple quantiles common_test_lib)
|
|
78
79
|
|
|
80
|
+
# Use CMAKE_CXX_STANDARD if defined, otherwise C++11
|
|
81
|
+
set(_integration_cxx_standard 11)
|
|
82
|
+
if(DEFINED CMAKE_CXX_STANDARD)
|
|
83
|
+
set(_integration_cxx_standard ${CMAKE_CXX_STANDARD})
|
|
84
|
+
endif()
|
|
79
85
|
set_target_properties(integration_test PROPERTIES
|
|
80
|
-
CXX_STANDARD
|
|
86
|
+
CXX_STANDARD ${_integration_cxx_standard}
|
|
81
87
|
CXX_STANDARD_REQUIRED YES
|
|
82
88
|
)
|
|
83
89
|
|
|
@@ -90,3 +96,39 @@ target_sources(integration_test
|
|
|
90
96
|
PRIVATE
|
|
91
97
|
integration_test.cpp
|
|
92
98
|
)
|
|
99
|
+
|
|
100
|
+
# Separate hardening test executable (header-only, no pre-compiled libs)
|
|
101
|
+
# This ensures the sketch code is compiled with C++17 + hardening
|
|
102
|
+
# Always build this target - it will use CMAKE_CXX_STANDARD if set (and >= 17), otherwise C++17
|
|
103
|
+
|
|
104
|
+
add_executable(hardening_test)
|
|
105
|
+
target_link_libraries(hardening_test common common_test_lib)
|
|
106
|
+
|
|
107
|
+
# Include directories for header-only sketch implementations
|
|
108
|
+
target_include_directories(hardening_test PRIVATE
|
|
109
|
+
${CMAKE_SOURCE_DIR}/quantiles/include
|
|
110
|
+
${CMAKE_SOURCE_DIR}/kll/include
|
|
111
|
+
${CMAKE_SOURCE_DIR}/req/include
|
|
112
|
+
${CMAKE_SOURCE_DIR}/common/include
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Use C++17 minimum for hardening tests
|
|
116
|
+
set(_hardening_cxx_standard 17)
|
|
117
|
+
if(DEFINED CMAKE_CXX_STANDARD AND CMAKE_CXX_STANDARD GREATER_EQUAL 17)
|
|
118
|
+
set(_hardening_cxx_standard ${CMAKE_CXX_STANDARD})
|
|
119
|
+
endif()
|
|
120
|
+
set_target_properties(hardening_test PROPERTIES
|
|
121
|
+
CXX_STANDARD ${_hardening_cxx_standard}
|
|
122
|
+
CXX_STANDARD_REQUIRED YES
|
|
123
|
+
)
|
|
124
|
+
message(STATUS "hardening_test will use C++${_hardening_cxx_standard}")
|
|
125
|
+
|
|
126
|
+
add_test(
|
|
127
|
+
NAME hardening_test
|
|
128
|
+
COMMAND hardening_test "[deserialize_hardening]"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
target_sources(hardening_test
|
|
132
|
+
PRIVATE
|
|
133
|
+
deserialize_hardening_test.cpp
|
|
134
|
+
)
|
|
@@ -0,0 +1,279 @@
|
|
|
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
|
+
#include <catch2/catch.hpp>
|
|
21
|
+
|
|
22
|
+
#include "binomial_bounds.hpp"
|
|
23
|
+
|
|
24
|
+
namespace datasketches {
|
|
25
|
+
|
|
26
|
+
TEST_CASE("binomial_bounds: get_lower_bound", "[common]") {
|
|
27
|
+
|
|
28
|
+
SECTION("num_samples == 0") {
|
|
29
|
+
double result = binomial_bounds::get_lower_bound(0, 0.5, 1);
|
|
30
|
+
REQUIRE(result == 0.0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
SECTION("theta == 1.0") {
|
|
34
|
+
double result = binomial_bounds::get_lower_bound(100, 1.0, 1);
|
|
35
|
+
REQUIRE(result == 100.0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
SECTION("num_samples == 1") {
|
|
39
|
+
double result = binomial_bounds::get_lower_bound(1, 0.5, 1);
|
|
40
|
+
REQUIRE(result >= 0.0);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
SECTION("num_samples == 1, stddev=2") {
|
|
44
|
+
double result = binomial_bounds::get_lower_bound(1, 0.5, 2);
|
|
45
|
+
REQUIRE(result >= 0.0);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
SECTION("num_samples == 1, stddev=3") {
|
|
49
|
+
double result = binomial_bounds::get_lower_bound(1, 0.5, 3);
|
|
50
|
+
REQUIRE(result >= 0.0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
SECTION("num_samples > 120") {
|
|
54
|
+
double result = binomial_bounds::get_lower_bound(121, 0.5, 1);
|
|
55
|
+
REQUIRE(result >= 0.0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
SECTION("num_samples > 120, stddev=2") {
|
|
59
|
+
double result = binomial_bounds::get_lower_bound(200, 0.5, 2);
|
|
60
|
+
REQUIRE(result >= 0.0);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
SECTION("num_samples > 120, stddev=3") {
|
|
64
|
+
double result = binomial_bounds::get_lower_bound(500, 0.5, 3);
|
|
65
|
+
REQUIRE(result >= 0.0);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
SECTION("2 <= num_samples <= 120 AND theta > (1-1e-5)") {
|
|
69
|
+
double result = binomial_bounds::get_lower_bound(50, 1.0 - 1e-6, 1);
|
|
70
|
+
REQUIRE(std::abs(result - 50.0) < 50.0 * 0.01);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
SECTION("2 <= num_samples <= 120 AND theta > (1-1e-5), stddev=2") {
|
|
74
|
+
double result = binomial_bounds::get_lower_bound(50, 1.0 - 1e-6, 2);
|
|
75
|
+
REQUIRE(std::abs(result - 50.0) < 50.0 * 0.01);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
SECTION("2 <= num_samples <= 120 AND theta > (1-1e-5), stddev=3") {
|
|
79
|
+
double result = binomial_bounds::get_lower_bound(50, 1.0 - 1e-6, 3);
|
|
80
|
+
REQUIRE(std::abs(result - 50.0) < 50.0 * 0.01);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
SECTION("2 <= num_samples <= 120 AND theta < num_samples/360") {
|
|
84
|
+
double result = binomial_bounds::get_lower_bound(100, 0.001, 1);
|
|
85
|
+
REQUIRE(result >= 0.0);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
SECTION("2 <= num_samples <= 120 AND theta < num_samples/360, stddev=2") {
|
|
89
|
+
double result = binomial_bounds::get_lower_bound(100, 0.001, 2);
|
|
90
|
+
REQUIRE(result >= 0.0);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
SECTION("2 <= num_samples <= 120 AND theta < num_samples/360, stddev=3") {
|
|
94
|
+
double result = binomial_bounds::get_lower_bound(100, 0.001, 3);
|
|
95
|
+
REQUIRE(result >= 0.0);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
SECTION("2 <= num_samples <= 120 AND middle range theta (exact calculation)") {
|
|
99
|
+
double result = binomial_bounds::get_lower_bound(10, 0.5, 1);
|
|
100
|
+
REQUIRE(result >= 0.0);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
SECTION("2 <= num_samples <= 120 AND middle range theta, stddev=2") {
|
|
104
|
+
double result = binomial_bounds::get_lower_bound(10, 0.5, 2);
|
|
105
|
+
REQUIRE(result >= 0.0);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
SECTION("2 <= num_samples <= 120 AND middle range theta, stddev=3") {
|
|
109
|
+
double result = binomial_bounds::get_lower_bound(10, 0.5, 3);
|
|
110
|
+
REQUIRE(result >= 0.0);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
SECTION("theta=0") {
|
|
114
|
+
REQUIRE_THROWS_AS(binomial_bounds::get_lower_bound(10, 0.0, 1), std::invalid_argument);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
SECTION("theta very close to 0") {
|
|
118
|
+
double result = binomial_bounds::get_lower_bound(10, 1e-10, 1);
|
|
119
|
+
REQUIRE(result >= 0.0);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
SECTION("num_samples=2 boundary") {
|
|
123
|
+
double result = binomial_bounds::get_lower_bound(2, 0.5, 1);
|
|
124
|
+
REQUIRE(result >= 0.0);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
SECTION("num_samples=120 boundary") {
|
|
128
|
+
double result = binomial_bounds::get_lower_bound(120, 0.5, 1);
|
|
129
|
+
REQUIRE(result >= 0.0);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
SECTION("estimate clamping case") {
|
|
133
|
+
double result = binomial_bounds::get_lower_bound(10, 0.9, 1);
|
|
134
|
+
double estimate = 10.0 / 0.9;
|
|
135
|
+
REQUIRE(result <= estimate);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
SECTION("invalid theta < 0") {
|
|
139
|
+
REQUIRE_THROWS_AS(binomial_bounds::get_lower_bound(100, -0.1, 1), std::invalid_argument);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
SECTION("invalid theta > 1") {
|
|
143
|
+
REQUIRE_THROWS_AS(binomial_bounds::get_lower_bound(100, 1.1, 1), std::invalid_argument);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
SECTION("invalid stddev = 0") {
|
|
147
|
+
REQUIRE_THROWS_AS(binomial_bounds::get_lower_bound(100, 0.5, 0), std::invalid_argument);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
SECTION("invalid stddev = 4") {
|
|
151
|
+
REQUIRE_THROWS_AS(binomial_bounds::get_lower_bound(100, 0.5, 4), std::invalid_argument);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
TEST_CASE("binomial_bounds: get_upper_bound", "[common]") {
|
|
156
|
+
|
|
157
|
+
SECTION("theta == 1.0") {
|
|
158
|
+
double result = binomial_bounds::get_upper_bound(100, 1.0, 1);
|
|
159
|
+
REQUIRE(result == 100.0);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
SECTION("num_samples == 0") {
|
|
163
|
+
double result = binomial_bounds::get_upper_bound(0, 0.5, 1);
|
|
164
|
+
REQUIRE(result > 0.0);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
SECTION("num_samples == 0, stddev=2") {
|
|
168
|
+
double result = binomial_bounds::get_upper_bound(0, 0.5, 2);
|
|
169
|
+
REQUIRE(result > 0.0);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
SECTION("num_samples == 0, stddev=3") {
|
|
173
|
+
double result = binomial_bounds::get_upper_bound(0, 0.5, 3);
|
|
174
|
+
REQUIRE(result > 0.0);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
SECTION("num_samples > 120") {
|
|
178
|
+
double result = binomial_bounds::get_upper_bound(121, 0.5, 1);
|
|
179
|
+
REQUIRE(result >= 0.0);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
SECTION("num_samples > 120, stddev=2") {
|
|
183
|
+
double result = binomial_bounds::get_upper_bound(200, 0.5, 2);
|
|
184
|
+
REQUIRE(result >= 0.0);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
SECTION("num_samples > 120, stddev=3") {
|
|
188
|
+
double result = binomial_bounds::get_upper_bound(500, 0.5, 3);
|
|
189
|
+
REQUIRE(result >= 0.0);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
SECTION("1 <= num_samples <= 120 AND theta > (1-1e-5)") {
|
|
193
|
+
double result = binomial_bounds::get_upper_bound(50, 1.0 - 1e-6, 1);
|
|
194
|
+
REQUIRE(result == 51.0);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
SECTION("1 <= num_samples <= 120 AND theta > (1-1e-5), stddev=2") {
|
|
198
|
+
double result = binomial_bounds::get_upper_bound(50, 1.0 - 1e-6, 2);
|
|
199
|
+
REQUIRE(result == 51.0);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
SECTION("1 <= num_samples <= 120 AND theta > (1-1e-5), stddev=3") {
|
|
203
|
+
double result = binomial_bounds::get_upper_bound(50, 1.0 - 1e-6, 3);
|
|
204
|
+
REQUIRE(result == 51.0);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
SECTION("1 <= num_samples <= 120 AND theta < num_samples/360") {
|
|
208
|
+
double result = binomial_bounds::get_upper_bound(100, 0.001, 1);
|
|
209
|
+
REQUIRE(result >= 0.0);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
SECTION("1 <= num_samples <= 120 AND theta < num_samples/360, stddev=2") {
|
|
213
|
+
double result = binomial_bounds::get_upper_bound(100, 0.001, 2);
|
|
214
|
+
REQUIRE(result >= 0.0);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
SECTION("1 <= num_samples <= 120 AND theta < num_samples/360, stddev=3") {
|
|
218
|
+
double result = binomial_bounds::get_upper_bound(100, 0.001, 3);
|
|
219
|
+
REQUIRE(result >= 0.0);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
SECTION("1 <= num_samples <= 120 AND middle range theta (exact calculation)") {
|
|
223
|
+
double result = binomial_bounds::get_upper_bound(10, 0.5, 1);
|
|
224
|
+
REQUIRE(result >= 0.0);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
SECTION("1 <= num_samples <= 120 AND middle range theta, stddev=2") {
|
|
228
|
+
double result = binomial_bounds::get_upper_bound(10, 0.5, 2);
|
|
229
|
+
REQUIRE(result >= 0.0);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
SECTION("1 <= num_samples <= 120 AND middle range theta, stddev=3") {
|
|
233
|
+
double result = binomial_bounds::get_upper_bound(10, 0.5, 3);
|
|
234
|
+
REQUIRE(result >= 0.0);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
SECTION("theta=0") {
|
|
238
|
+
REQUIRE_THROWS_AS(binomial_bounds::get_upper_bound(10, 0.0, 1), std::invalid_argument);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
SECTION("theta very close to 0") {
|
|
242
|
+
double result = binomial_bounds::get_upper_bound(10, 1e-10, 1);
|
|
243
|
+
REQUIRE(result >= 0.0);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
SECTION("num_samples=1 boundary") {
|
|
247
|
+
double result = binomial_bounds::get_upper_bound(1, 0.5, 1);
|
|
248
|
+
REQUIRE(result >= 0.0);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
SECTION("num_samples=120 boundary") {
|
|
252
|
+
double result = binomial_bounds::get_upper_bound(120, 0.5, 1);
|
|
253
|
+
REQUIRE(result >= 0.0);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
SECTION("estimate clamping case") {
|
|
257
|
+
double result = binomial_bounds::get_upper_bound(10, 0.9, 1);
|
|
258
|
+
double estimate = 10.0 / 0.9;
|
|
259
|
+
REQUIRE(result >= estimate);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
SECTION("invalid theta < 0") {
|
|
263
|
+
REQUIRE_THROWS_AS(binomial_bounds::get_upper_bound(100, -0.1, 1), std::invalid_argument);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
SECTION("invalid theta > 1") {
|
|
267
|
+
REQUIRE_THROWS_AS(binomial_bounds::get_upper_bound(100, 1.1, 1), std::invalid_argument);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
SECTION("invalid stddev = 0") {
|
|
271
|
+
REQUIRE_THROWS_AS(binomial_bounds::get_upper_bound(100, 0.5, 0), std::invalid_argument);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
SECTION("invalid stddev = 4") {
|
|
275
|
+
REQUIRE_THROWS_AS(binomial_bounds::get_upper_bound(100, 0.5, 4), std::invalid_argument);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
} /* namespace datasketches */
|
|
@@ -0,0 +1,188 @@
|
|
|
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
|
+
#include <catch2/catch.hpp>
|
|
21
|
+
#include <sstream>
|
|
22
|
+
#include <vector>
|
|
23
|
+
|
|
24
|
+
// Include all affected sketch types
|
|
25
|
+
#include <quantiles_sketch.hpp>
|
|
26
|
+
#include <kll_sketch.hpp>
|
|
27
|
+
#include <req_sketch.hpp>
|
|
28
|
+
|
|
29
|
+
namespace datasketches {
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Test for fix of issue #477:
|
|
33
|
+
* BUG: SIGABRT in deserialize(): dereferencing empty std::optional (libc++ verbose_abort)
|
|
34
|
+
*
|
|
35
|
+
* These tests exercise the actual deserialization code path that contained the bug.
|
|
36
|
+
* With buggy code (&*tmp on empty optional) and hardening enabled, these will SIGABRT.
|
|
37
|
+
* With fixed code (aligned_storage), these pass normally.
|
|
38
|
+
*
|
|
39
|
+
* IMPORTANT: These tests actually call deserialize() on multi-item sketches, which
|
|
40
|
+
* exercises the buggy code path where min/max are deserialized.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
TEST_CASE("quantiles_sketch: deserialize multi-item sketch", "[deserialize_hardening]") {
|
|
44
|
+
// Create sketch with multiple items (so min/max are stored in serialization)
|
|
45
|
+
quantiles_sketch<double> sketch(128);
|
|
46
|
+
for (int i = 0; i < 1000; i++) {
|
|
47
|
+
sketch.update(static_cast<double>(i));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Serialize
|
|
51
|
+
auto bytes = sketch.serialize();
|
|
52
|
+
|
|
53
|
+
// Deserialize - WITH BUGGY CODE AND HARDENING, THIS WILL SIGABRT HERE
|
|
54
|
+
// The bug is: sd.deserialize(is, &*tmp, 1) where tmp is empty optional
|
|
55
|
+
auto sketch2 = quantiles_sketch<double>::deserialize(bytes.data(), bytes.size());
|
|
56
|
+
|
|
57
|
+
// Verify deserialization worked correctly
|
|
58
|
+
REQUIRE(sketch2.get_n() == sketch.get_n());
|
|
59
|
+
REQUIRE(sketch2.get_min_item() == sketch.get_min_item());
|
|
60
|
+
REQUIRE(sketch2.get_max_item() == sketch.get_max_item());
|
|
61
|
+
REQUIRE(sketch2.get_quantile(0.5) == sketch.get_quantile(0.5));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
TEST_CASE("quantiles_sketch: deserialize from stream", "[deserialize_hardening]") {
|
|
65
|
+
quantiles_sketch<float> sketch(256);
|
|
66
|
+
for (int i = 0; i < 2000; i++) {
|
|
67
|
+
sketch.update(static_cast<float>(i) * 0.5f);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Serialize to stream
|
|
71
|
+
std::stringstream ss;
|
|
72
|
+
sketch.serialize(ss);
|
|
73
|
+
|
|
74
|
+
// Deserialize from stream - exercises the buggy code path
|
|
75
|
+
auto sketch2 = quantiles_sketch<float>::deserialize(ss);
|
|
76
|
+
|
|
77
|
+
REQUIRE(sketch2.get_n() == sketch.get_n());
|
|
78
|
+
REQUIRE(sketch2.get_min_item() == sketch.get_min_item());
|
|
79
|
+
REQUIRE(sketch2.get_max_item() == sketch.get_max_item());
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
TEST_CASE("kll_sketch: deserialize multi-item sketch", "[deserialize_hardening]") {
|
|
83
|
+
kll_sketch<float> sketch(200);
|
|
84
|
+
for (int i = 0; i < 1500; i++) {
|
|
85
|
+
sketch.update(static_cast<float>(i));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
auto bytes = sketch.serialize();
|
|
89
|
+
|
|
90
|
+
// Deserialize - exercises buggy &*tmp code path
|
|
91
|
+
auto sketch2 = kll_sketch<float>::deserialize(bytes.data(), bytes.size());
|
|
92
|
+
|
|
93
|
+
REQUIRE(sketch2.get_n() == sketch.get_n());
|
|
94
|
+
REQUIRE(sketch2.get_min_item() == sketch.get_min_item());
|
|
95
|
+
REQUIRE(sketch2.get_max_item() == sketch.get_max_item());
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
TEST_CASE("kll_sketch: deserialize from stream", "[deserialize_hardening]") {
|
|
99
|
+
kll_sketch<int> sketch(400);
|
|
100
|
+
for (int i = 0; i < 3000; i++) {
|
|
101
|
+
sketch.update(i);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
std::stringstream ss;
|
|
105
|
+
sketch.serialize(ss);
|
|
106
|
+
|
|
107
|
+
// Deserialize from stream
|
|
108
|
+
auto sketch2 = kll_sketch<int>::deserialize(ss);
|
|
109
|
+
|
|
110
|
+
REQUIRE(sketch2.get_n() == sketch.get_n());
|
|
111
|
+
REQUIRE(sketch2.get_min_item() == sketch.get_min_item());
|
|
112
|
+
REQUIRE(sketch2.get_max_item() == sketch.get_max_item());
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
TEST_CASE("req_sketch: deserialize multi-level sketch", "[deserialize_hardening]") {
|
|
116
|
+
// REQ sketch only has the bug when num_levels > 1
|
|
117
|
+
// We need to add enough items to trigger multiple levels
|
|
118
|
+
req_sketch<float> sketch(12);
|
|
119
|
+
for (int i = 0; i < 10000; i++) {
|
|
120
|
+
sketch.update(static_cast<float>(i));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
auto bytes = sketch.serialize();
|
|
124
|
+
|
|
125
|
+
// Deserialize - exercises buggy code path when num_levels > 1
|
|
126
|
+
auto sketch2 = req_sketch<float>::deserialize(bytes.data(), bytes.size());
|
|
127
|
+
|
|
128
|
+
REQUIRE(sketch2.get_n() == sketch.get_n());
|
|
129
|
+
REQUIRE(sketch2.get_min_item() == sketch.get_min_item());
|
|
130
|
+
REQUIRE(sketch2.get_max_item() == sketch.get_max_item());
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
TEST_CASE("req_sketch: deserialize from stream", "[deserialize_hardening]") {
|
|
134
|
+
req_sketch<double> sketch(20);
|
|
135
|
+
for (int i = 0; i < 15000; i++) {
|
|
136
|
+
sketch.update(static_cast<double>(i) * 0.1);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
std::stringstream ss;
|
|
140
|
+
sketch.serialize(ss);
|
|
141
|
+
|
|
142
|
+
// Deserialize from stream
|
|
143
|
+
auto sketch2 = req_sketch<double>::deserialize(ss);
|
|
144
|
+
|
|
145
|
+
REQUIRE(sketch2.get_n() == sketch.get_n());
|
|
146
|
+
REQUIRE(sketch2.get_min_item() == sketch.get_min_item());
|
|
147
|
+
REQUIRE(sketch2.get_max_item() == sketch.get_max_item());
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
TEST_CASE("multiple sketch types: stress test", "[deserialize_hardening]") {
|
|
151
|
+
SECTION("quantiles with various sizes") {
|
|
152
|
+
for (int k : {64, 128, 256}) {
|
|
153
|
+
quantiles_sketch<int> sketch(k);
|
|
154
|
+
for (int i = 0; i < 5000; i++) {
|
|
155
|
+
sketch.update(i);
|
|
156
|
+
}
|
|
157
|
+
auto bytes = sketch.serialize();
|
|
158
|
+
auto sketch2 = quantiles_sketch<int>::deserialize(bytes.data(), bytes.size());
|
|
159
|
+
REQUIRE(sketch2.get_n() == sketch.get_n());
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
SECTION("kll with various sizes") {
|
|
164
|
+
for (int k : {100, 200, 400}) {
|
|
165
|
+
kll_sketch<double> sketch(k);
|
|
166
|
+
for (int i = 0; i < 4000; i++) {
|
|
167
|
+
sketch.update(static_cast<double>(i) / 10.0);
|
|
168
|
+
}
|
|
169
|
+
auto bytes = sketch.serialize();
|
|
170
|
+
auto sketch2 = kll_sketch<double>::deserialize(bytes.data(), bytes.size());
|
|
171
|
+
REQUIRE(sketch2.get_n() == sketch.get_n());
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
SECTION("req with various sizes") {
|
|
176
|
+
for (int k : {12, 20}) {
|
|
177
|
+
req_sketch<float> sketch(k);
|
|
178
|
+
for (int i = 0; i < 8000; i++) {
|
|
179
|
+
sketch.update(static_cast<float>(i));
|
|
180
|
+
}
|
|
181
|
+
auto bytes = sketch.serialize();
|
|
182
|
+
auto sketch2 = req_sketch<float>::deserialize(bytes.data(), bytes.size());
|
|
183
|
+
REQUIRE(sketch2.get_n() == sketch.get_n());
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
} // namespace datasketches
|