datasketches 0.5.1 → 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 +9 -0
- data/ext/datasketches/cpc_wrapper.cpp +8 -9
- data/ext/datasketches/fi_wrapper.cpp +4 -5
- data/ext/datasketches/hll_wrapper.cpp +9 -10
- data/ext/datasketches/kll_wrapper.cpp +13 -12
- data/ext/datasketches/theta_wrapper.cpp +11 -13
- data/ext/datasketches/vo_wrapper.cpp +1 -2
- 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
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
#include <sstream>
|
|
24
24
|
#include <vector>
|
|
25
25
|
#include <stdexcept>
|
|
26
|
+
#include <algorithm>
|
|
26
27
|
|
|
27
28
|
#include "binomial_bounds.hpp"
|
|
28
29
|
#include "theta_helpers.hpp"
|
|
@@ -239,8 +240,21 @@ auto update_theta_sketch_alloc<A>::end() const -> const_iterator {
|
|
|
239
240
|
}
|
|
240
241
|
|
|
241
242
|
template<typename A>
|
|
242
|
-
compact_theta_sketch_alloc<A> update_theta_sketch_alloc<A>::compact(bool ordered) const {
|
|
243
|
-
return compact_theta_sketch_alloc<A>(*this, ordered);
|
|
243
|
+
compact_theta_sketch_alloc<A> update_theta_sketch_alloc<A>::compact(bool ordered, bool trim) const {
|
|
244
|
+
if (!trim) return compact_theta_sketch_alloc<A>(*this, ordered);
|
|
245
|
+
|
|
246
|
+
std::vector<uint64_t, A> entries(table_.allocator_);
|
|
247
|
+
if (this->is_empty()) {
|
|
248
|
+
return compact_theta_sketch_alloc<A>(true, true, this->get_seed_hash(), this->get_theta64(), std::move(entries));
|
|
249
|
+
}
|
|
250
|
+
// copy first: this method is const, and quick select would permute the source table
|
|
251
|
+
entries.reserve(this->get_num_retained());
|
|
252
|
+
std::copy(this->begin(), this->end(), std::back_inserter(entries));
|
|
253
|
+
uint64_t theta = this->get_theta64();
|
|
254
|
+
const uint32_t nominal_size = 1 << table_.lg_nom_size_;
|
|
255
|
+
theta = trim_to_nominal<trivial_extract_key>(entries, nominal_size, theta);
|
|
256
|
+
if (ordered) std::sort(entries.begin(), entries.end());
|
|
257
|
+
return compact_theta_sketch_alloc<A>(false, ordered, this->get_seed_hash(), theta, std::move(entries));
|
|
244
258
|
}
|
|
245
259
|
|
|
246
260
|
template<typename A>
|
|
@@ -315,7 +329,7 @@ uint32_t compact_theta_sketch_alloc<A>::get_num_retained() const {
|
|
|
315
329
|
|
|
316
330
|
template<typename A>
|
|
317
331
|
uint16_t compact_theta_sketch_alloc<A>::get_seed_hash() const {
|
|
318
|
-
return seed_hash_;
|
|
332
|
+
return is_empty_ ? 0 : seed_hash_;
|
|
319
333
|
}
|
|
320
334
|
|
|
321
335
|
template<typename A>
|
|
@@ -376,7 +390,7 @@ size_t compact_theta_sketch_alloc<A>::get_compressed_serialized_size_bytes(uint8
|
|
|
376
390
|
|
|
377
391
|
template<typename A>
|
|
378
392
|
void compact_theta_sketch_alloc<A>::serialize(std::ostream& os) const {
|
|
379
|
-
const uint8_t preamble_longs =
|
|
393
|
+
const uint8_t preamble_longs = get_preamble_longs(false);
|
|
380
394
|
write(os, preamble_longs);
|
|
381
395
|
write(os, UNCOMPRESSED_SERIAL_VERSION);
|
|
382
396
|
write(os, SKETCH_TYPE);
|
|
@@ -385,7 +399,8 @@ void compact_theta_sketch_alloc<A>::serialize(std::ostream& os) const {
|
|
|
385
399
|
(1 << flags::IS_COMPACT) |
|
|
386
400
|
(1 << flags::IS_READ_ONLY) |
|
|
387
401
|
(this->is_empty() ? 1 << flags::IS_EMPTY : 0) |
|
|
388
|
-
(this->is_ordered() ? 1 << flags::IS_ORDERED : 0)
|
|
402
|
+
(this->is_ordered() ? 1 << flags::IS_ORDERED : 0) |
|
|
403
|
+
(is_single_item() ? 1 << flags::IS_SINGLE_ITEM : 0)
|
|
389
404
|
);
|
|
390
405
|
write(os, flags_byte);
|
|
391
406
|
write(os, get_seed_hash());
|
|
@@ -411,7 +426,8 @@ auto compact_theta_sketch_alloc<A>::serialize(unsigned header_size_bytes) const
|
|
|
411
426
|
(1 << flags::IS_COMPACT) |
|
|
412
427
|
(1 << flags::IS_READ_ONLY) |
|
|
413
428
|
(this->is_empty() ? 1 << flags::IS_EMPTY : 0) |
|
|
414
|
-
(this->is_ordered() ? 1 << flags::IS_ORDERED : 0)
|
|
429
|
+
(this->is_ordered() ? 1 << flags::IS_ORDERED : 0) |
|
|
430
|
+
(is_single_item() ? 1 << flags::IS_SINGLE_ITEM : 0)
|
|
415
431
|
);
|
|
416
432
|
*ptr++ = flags_byte;
|
|
417
433
|
ptr += copy_to_mem(get_seed_hash(), ptr);
|
|
@@ -424,6 +440,12 @@ auto compact_theta_sketch_alloc<A>::serialize(unsigned header_size_bytes) const
|
|
|
424
440
|
return bytes;
|
|
425
441
|
}
|
|
426
442
|
|
|
443
|
+
template<typename A>
|
|
444
|
+
bool compact_theta_sketch_alloc<A>::is_single_item() const {
|
|
445
|
+
// one entry in exact mode: the same condition Java uses to set its SingleItem flag
|
|
446
|
+
return entries_.size() == 1 && !this->is_estimation_mode();
|
|
447
|
+
}
|
|
448
|
+
|
|
427
449
|
template<typename A>
|
|
428
450
|
bool compact_theta_sketch_alloc<A>::is_suitable_for_compression() const {
|
|
429
451
|
if (!this->is_ordered() || entries_.size() == 0 ||
|
|
@@ -459,7 +481,7 @@ uint8_t compact_theta_sketch_alloc<A>::compute_entry_bits() const {
|
|
|
459
481
|
|
|
460
482
|
template<typename A>
|
|
461
483
|
void compact_theta_sketch_alloc<A>::serialize_version_4(std::ostream& os) const {
|
|
462
|
-
const uint8_t preamble_longs =
|
|
484
|
+
const uint8_t preamble_longs = get_preamble_longs(true);
|
|
463
485
|
const uint8_t entry_bits = compute_entry_bits();
|
|
464
486
|
const uint8_t num_entries_bytes = get_num_entries_bytes();
|
|
465
487
|
|
|
@@ -674,7 +696,9 @@ compact_theta_sketch_alloc<A> compact_theta_sketch_alloc<A>::deserialize_v4(
|
|
|
674
696
|
uint8_t preamble_longs, std::istream& is, uint64_t seed, const A& allocator)
|
|
675
697
|
{
|
|
676
698
|
const auto entry_bits = read<uint8_t>(is);
|
|
699
|
+
compact_theta_sketch_parser<true>::check_v4_entry_bits(entry_bits);
|
|
677
700
|
const auto num_entries_bytes = read<uint8_t>(is);
|
|
701
|
+
compact_theta_sketch_parser<true>::check_v4_num_entries_bytes(num_entries_bytes);
|
|
678
702
|
const auto flags_byte = read<uint8_t>(is);
|
|
679
703
|
const auto seed_hash = read<uint16_t>(is);
|
|
680
704
|
const bool is_empty = flags_byte & (1 << flags::IS_EMPTY);
|
|
@@ -782,7 +806,7 @@ uint32_t wrapped_compact_theta_sketch_alloc<A>::get_num_retained() const {
|
|
|
782
806
|
|
|
783
807
|
template<typename A>
|
|
784
808
|
uint16_t wrapped_compact_theta_sketch_alloc<A>::get_seed_hash() const {
|
|
785
|
-
return data_.seed_hash;
|
|
809
|
+
return is_empty() ? 0 : data_.seed_hash;
|
|
786
810
|
}
|
|
787
811
|
|
|
788
812
|
template<typename A>
|
|
@@ -817,23 +841,15 @@ num_entries_(num_entries),
|
|
|
817
841
|
index_(index),
|
|
818
842
|
previous_(0),
|
|
819
843
|
is_block_mode_(num_entries_ >= 8),
|
|
820
|
-
buf_i_(0),
|
|
821
844
|
offset_(0)
|
|
822
845
|
{
|
|
823
846
|
if (entry_bits == 64) { // no compression
|
|
824
847
|
ptr_ = reinterpret_cast<const uint64_t*>(ptr) + index;
|
|
825
848
|
} else if (index < num_entries) {
|
|
826
849
|
if (is_block_mode_) {
|
|
827
|
-
|
|
828
|
-
ptr_ = reinterpret_cast<const uint8_t*>(ptr_) + entry_bits_;
|
|
829
|
-
for (int i = 0; i < 8; ++i) {
|
|
830
|
-
buffer_[i] += previous_;
|
|
831
|
-
previous_ = buffer_[i];
|
|
832
|
-
}
|
|
850
|
+
unpack8();
|
|
833
851
|
} else {
|
|
834
|
-
|
|
835
|
-
buffer_[0] += previous_;
|
|
836
|
-
previous_ = buffer_[0];
|
|
852
|
+
unpack1();
|
|
837
853
|
}
|
|
838
854
|
}
|
|
839
855
|
}
|
|
@@ -844,35 +860,41 @@ auto wrapped_compact_theta_sketch_alloc<Allocator>::const_iterator::operator++()
|
|
|
844
860
|
ptr_ = reinterpret_cast<const uint64_t*>(ptr_) + 1;
|
|
845
861
|
return *this;
|
|
846
862
|
}
|
|
847
|
-
++index_
|
|
848
|
-
if (index_ < num_entries_) {
|
|
863
|
+
if (++index_ < num_entries_) {
|
|
849
864
|
if (is_block_mode_) {
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
if (index_ + 8 < num_entries_) {
|
|
854
|
-
unpack_bits_block8(buffer_, reinterpret_cast<const uint8_t*>(ptr_), entry_bits_);
|
|
855
|
-
ptr_ = reinterpret_cast<const uint8_t*>(ptr_) + entry_bits_;
|
|
856
|
-
for (int i = 0; i < 8; ++i) {
|
|
857
|
-
buffer_[i] += previous_;
|
|
858
|
-
previous_ = buffer_[i];
|
|
859
|
-
}
|
|
865
|
+
if ((index_ & 7) == 0) {
|
|
866
|
+
if (num_entries_ - index_ >= 8) {
|
|
867
|
+
unpack8();
|
|
860
868
|
} else {
|
|
861
869
|
is_block_mode_ = false;
|
|
862
|
-
|
|
863
|
-
buffer_[0] += previous_;
|
|
864
|
-
previous_ = buffer_[0];
|
|
870
|
+
unpack1();
|
|
865
871
|
}
|
|
866
872
|
}
|
|
867
873
|
} else {
|
|
868
|
-
|
|
869
|
-
buffer_[0] += previous_;
|
|
870
|
-
previous_ = buffer_[0];
|
|
874
|
+
unpack1();
|
|
871
875
|
}
|
|
872
876
|
}
|
|
873
877
|
return *this;
|
|
874
878
|
}
|
|
875
879
|
|
|
880
|
+
template<typename Allocator>
|
|
881
|
+
void wrapped_compact_theta_sketch_alloc<Allocator>::const_iterator::unpack1() {
|
|
882
|
+
const uint32_t i = index_ & 7;
|
|
883
|
+
offset_ = unpack_bits(buffer_[i], entry_bits_, reinterpret_cast<const uint8_t*&>(ptr_), offset_);
|
|
884
|
+
buffer_[i] += previous_;
|
|
885
|
+
previous_ = buffer_[i];
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
template<typename Allocator>
|
|
889
|
+
void wrapped_compact_theta_sketch_alloc<Allocator>::const_iterator::unpack8() {
|
|
890
|
+
unpack_bits_block8(buffer_, reinterpret_cast<const uint8_t*>(ptr_), entry_bits_);
|
|
891
|
+
ptr_ = reinterpret_cast<const uint8_t*>(ptr_) + entry_bits_;
|
|
892
|
+
for (int i = 0; i < 8; ++i) {
|
|
893
|
+
buffer_[i] += previous_;
|
|
894
|
+
previous_ = buffer_[i];
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
|
|
876
898
|
template<typename Allocator>
|
|
877
899
|
auto wrapped_compact_theta_sketch_alloc<Allocator>::const_iterator::operator++(int) -> const_iterator {
|
|
878
900
|
const_iterator tmp(*this);
|
|
@@ -895,13 +917,13 @@ bool wrapped_compact_theta_sketch_alloc<Allocator>::const_iterator::operator==(c
|
|
|
895
917
|
template<typename Allocator>
|
|
896
918
|
auto wrapped_compact_theta_sketch_alloc<Allocator>::const_iterator::operator*() const -> reference {
|
|
897
919
|
if (entry_bits_ == 64) return *reinterpret_cast<const uint64_t*>(ptr_);
|
|
898
|
-
return buffer_[
|
|
920
|
+
return buffer_[index_ & 7];
|
|
899
921
|
}
|
|
900
922
|
|
|
901
923
|
template<typename Allocator>
|
|
902
924
|
auto wrapped_compact_theta_sketch_alloc<Allocator>::const_iterator::operator->() const -> pointer {
|
|
903
925
|
if (entry_bits_ == 64) return reinterpret_cast<const uint64_t*>(ptr_);
|
|
904
|
-
return buffer_ +
|
|
926
|
+
return buffer_ + (index_ & 7);
|
|
905
927
|
}
|
|
906
928
|
|
|
907
929
|
} /* namespace datasketches */
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
#include <stdexcept>
|
|
25
25
|
|
|
26
26
|
#include "conditional_forward.hpp"
|
|
27
|
+
#include "theta_helpers.hpp"
|
|
27
28
|
|
|
28
29
|
namespace datasketches {
|
|
29
30
|
|
|
@@ -70,12 +71,7 @@ CS theta_union_base<EN, EK, P, S, CS, A>::get_result(bool ordered) const {
|
|
|
70
71
|
} else {
|
|
71
72
|
std::copy_if(table_.begin(), table_.end(), std::back_inserter(entries), key_not_zero_less_than<uint64_t, EN, EK>(theta));
|
|
72
73
|
}
|
|
73
|
-
|
|
74
|
-
std::nth_element(entries.begin(), entries.begin() + nominal_num, entries.end(), comparator());
|
|
75
|
-
theta = EK()(entries[nominal_num]);
|
|
76
|
-
entries.erase(entries.begin() + nominal_num, entries.end());
|
|
77
|
-
entries.shrink_to_fit();
|
|
78
|
-
}
|
|
74
|
+
theta = trim_to_nominal<EK>(entries, nominal_num, theta);
|
|
79
75
|
if (ordered) std::sort(entries.begin(), entries.end(), comparator());
|
|
80
76
|
return CS(table_.is_empty_, ordered, compute_seed_hash(table_.seed_), theta, std::move(entries));
|
|
81
77
|
}
|
|
@@ -265,7 +265,7 @@ void theta_update_sketch_base<EN, EK, A>::reset() {
|
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
267
|
const uint8_t starting_lg_size = theta_build_helper<true>::starting_sub_multiple(
|
|
268
|
-
lg_nom_size_ + 1, theta_constants::
|
|
268
|
+
lg_nom_size_ + 1, theta_constants::MIN_LG_ARR, static_cast<uint8_t>(rf_));
|
|
269
269
|
if (starting_lg_size != lg_cur_size_) {
|
|
270
270
|
allocator_.deallocate(entries_, cur_size);
|
|
271
271
|
lg_cur_size_ = starting_lg_size;
|
|
@@ -346,7 +346,7 @@ uint64_t theta_base_builder<Derived, Allocator>::starting_theta() const {
|
|
|
346
346
|
|
|
347
347
|
template<typename Derived, typename Allocator>
|
|
348
348
|
uint8_t theta_base_builder<Derived, Allocator>::starting_lg_size() const {
|
|
349
|
-
return theta_build_helper<true>::starting_sub_multiple(lg_k_ + 1, theta_constants::
|
|
349
|
+
return theta_build_helper<true>::starting_sub_multiple(lg_k_ + 1, theta_constants::MIN_LG_ARR, static_cast<uint8_t>(rf_));
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
// iterator
|
|
@@ -80,4 +80,54 @@ TEST_CASE("pack unpack blocks") {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
TEST_CASE("pack bits unpack blocks") {
|
|
84
|
+
uint64_t value = 0; // arbitrary starting value
|
|
85
|
+
for (int m = 0; m < 10000; ++m) {
|
|
86
|
+
for (uint8_t bits = 1; bits <= 63; ++bits) {
|
|
87
|
+
const uint64_t mask = (1ULL << bits) - 1;
|
|
88
|
+
std::vector<uint64_t> input(8, 0);
|
|
89
|
+
for (int i = 0; i < 8; ++i) {
|
|
90
|
+
input[i] = value & mask;
|
|
91
|
+
value += IGOLDEN64;
|
|
92
|
+
}
|
|
93
|
+
std::vector<uint8_t> bytes(bits, 0);
|
|
94
|
+
uint8_t offset = 0;
|
|
95
|
+
uint8_t* ptr = bytes.data();
|
|
96
|
+
for (int i = 0; i < 8; ++i) {
|
|
97
|
+
offset = pack_bits(input[i], bits, ptr, offset);
|
|
98
|
+
}
|
|
99
|
+
std::vector<uint64_t> output(8, 0);
|
|
100
|
+
unpack_bits_block8(output.data(), bytes.data(), bits);
|
|
101
|
+
for (int i = 0; i < 8; ++i) {
|
|
102
|
+
REQUIRE(input[i] == output[i]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
TEST_CASE("pack blocks unpack bits") {
|
|
109
|
+
uint64_t value = 111; // arbitrary starting value
|
|
110
|
+
for (int m = 0; m < 10000; ++m) {
|
|
111
|
+
for (uint8_t bits = 1; bits <= 63; ++bits) {
|
|
112
|
+
const uint64_t mask = (1ULL << bits) - 1;
|
|
113
|
+
std::vector<uint64_t> input(8, 0);
|
|
114
|
+
for (int i = 0; i < 8; ++i) {
|
|
115
|
+
input[i] = value & mask;
|
|
116
|
+
value += IGOLDEN64;
|
|
117
|
+
}
|
|
118
|
+
std::vector<uint8_t> bytes(bits, 0);
|
|
119
|
+
pack_bits_block8(input.data(), bytes.data(), bits);
|
|
120
|
+
std::vector<uint64_t> output(8, 0);
|
|
121
|
+
uint8_t offset = 0;
|
|
122
|
+
const uint8_t* cptr = bytes.data();
|
|
123
|
+
for (int i = 0; i < 8; ++i) {
|
|
124
|
+
offset = unpack_bits(output[i], bits, cptr, offset);
|
|
125
|
+
}
|
|
126
|
+
for (int i = 0; i < 8; ++i) {
|
|
127
|
+
REQUIRE(input[i] == output[i]);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
83
133
|
} /* namespace datasketches */
|
|
@@ -241,6 +241,28 @@ TEST_CASE("theta a-not-b: seed mismatch", "[theta_a_not_b]") {
|
|
|
241
241
|
REQUIRE_THROWS_AS(a_not_b.compute(sketch, sketch), std::invalid_argument);
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
+
TEST_CASE("theta a-not-b: empty B with different seed must be ignored", "[theta_a_not_b]") {
|
|
245
|
+
// An empty sketch carries no hashes, so its seed hash is meaningless. Deserialization,
|
|
246
|
+
// theta_union::update() and theta_intersection::update() all skip the seed hash check
|
|
247
|
+
// for empty inputs; a-not-b must do the same. This matters across languages because
|
|
248
|
+
// datasketches-java serializes every empty compact sketch with a seed hash of 0.
|
|
249
|
+
|
|
250
|
+
// A: non-empty, but with zero retained entries (all hashes exceeded theta)
|
|
251
|
+
update_theta_sketch a = update_theta_sketch::builder().set_p(1e-6f).build();
|
|
252
|
+
a.update(1);
|
|
253
|
+
REQUIRE_FALSE(a.is_empty());
|
|
254
|
+
REQUIRE(a.get_num_retained() == 0);
|
|
255
|
+
|
|
256
|
+
// B: empty, built with a different seed
|
|
257
|
+
compact_theta_sketch b = update_theta_sketch::builder().set_seed(123).build().compact();
|
|
258
|
+
REQUIRE(b.is_empty());
|
|
259
|
+
|
|
260
|
+
theta_a_not_b a_not_b; // default seed
|
|
261
|
+
compact_theta_sketch result = a_not_b.compute(a.compact(), b);
|
|
262
|
+
REQUIRE_FALSE(result.is_empty());
|
|
263
|
+
REQUIRE(result.get_num_retained() == 0);
|
|
264
|
+
}
|
|
265
|
+
|
|
244
266
|
TEST_CASE("theta a-not-b: issue #152", "[theta_a_not_b]") {
|
|
245
267
|
update_theta_sketch a = update_theta_sketch::builder().build();
|
|
246
268
|
int value = 0;
|