This is an automated email from the ASF dual-hosted git repository.
tisonkun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datasketches-rust.git
The following commit(s) were added to refs/heads/main by this push:
new c8b20c8 refactor: align internal symbol visibility (#245)
c8b20c8 is described below
commit c8b20c8238a19cad15dd78196dbfff510e944773
Author: tison <[email protected]>
AuthorDate: Sat Aug 29 16:07:29 2026 +0800
refactor: align internal symbol visibility (#245)
---
CONTRIBUTING.md | 6 +++
datasketches/src/codec/assert.rs | 8 +--
datasketches/src/common/inv_pow2.rs | 2 +-
datasketches/src/countmin/serialization.rs | 8 +--
datasketches/src/cpc/compression.rs | 15 ++----
datasketches/src/cpc/compression_data.rs | 12 ++---
datasketches/src/cpc/estimator.rs | 6 +--
datasketches/src/cpc/kxp_byte_lookup.rs | 2 +-
datasketches/src/cpc/pair_table.rs | 2 +-
datasketches/src/cpc/serialization.rs | 12 ++---
datasketches/src/cpc/sketch.rs | 2 +-
.../src/frequencies/reverse_purge_item_hash_map.rs | 2 +-
datasketches/src/hash/seed.rs | 4 +-
datasketches/src/hll/array4.rs | 12 ++---
datasketches/src/hll/array6.rs | 8 +--
datasketches/src/hll/array8.rs | 16 +++---
datasketches/src/hll/estimator.rs | 17 +++----
datasketches/src/req/compactor.rs | 58 ++++++++--------------
datasketches/src/req/serialization.rs | 22 ++++----
datasketches/src/req/sketch.rs | 4 +-
datasketches/src/tdigest/serialization.rs | 16 +++---
datasketches/src/tdigest/sketch.rs | 6 +--
datasketches/src/thetafamily/theta/bit_pack.rs | 10 ++--
datasketches/src/thetafamily/theta/hash_table.rs | 2 +-
.../src/thetafamily/theta/serialization.rs | 10 ++--
datasketches/src/thetafamily/tuple/hash_table.rs | 2 +-
.../src/thetafamily/tuple/serialization.rs | 8 +--
27 files changed, 126 insertions(+), 146 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3812d38..4ef490b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -80,6 +80,12 @@ cargo bench --package benchmarks --bench benchmarks --
cpc::serde
- End summary sentences with punctuation, and format Rust identifiers,
literals, and numeric ranges as inline code.
- Put contract sections and compatibility notes before examples. When
applicable, order sections as `# Errors`, `# Panics`, and `# Examples`. Include
only sections that describe an actual contract.
+## Visibility
+
+- Let module visibility define the boundary for implementation items. Inside a
private module, use `pub` when an item must be available outside its defining
module. Inside a `pub(crate)` module, use `pub` when the item should be
available wherever that module is visible. Do not repeat an enclosing
restriction when it adds no narrower boundary.
+- Keep items private when they are used only by their defining module and its
descendants.
+- For items reachable through a public module or a re-exported public type,
use the narrowest visibility that supports their internal callers. Reserve
unrestricted `pub` for intentional public API.
+
## Changelog
- Update `CHANGELOG.md` in the same pull request for significant user-visible
changes. Compare the final behavior with the latest release tag rather than
recording the sequence of commits that produced it.
diff --git a/datasketches/src/codec/assert.rs b/datasketches/src/codec/assert.rs
index 2ef5ee5..71d18ec 100644
--- a/datasketches/src/codec/assert.rs
+++ b/datasketches/src/codec/assert.rs
@@ -20,11 +20,11 @@ use std::ops::RangeBounds;
use crate::error::Error;
-pub(crate) fn insufficient_data(tag: &'static str) -> impl
FnOnce(std::io::Error) -> Error {
+pub fn insufficient_data(tag: &'static str) -> impl FnOnce(std::io::Error) ->
Error {
move |_| Error::insufficient_data(tag)
}
-pub(crate) fn ensure_serial_version_is(expected: u8, actual: u8) -> Result<(),
Error> {
+pub fn ensure_serial_version_is(expected: u8, actual: u8) -> Result<(), Error>
{
if expected == actual {
Ok(())
} else {
@@ -34,7 +34,7 @@ pub(crate) fn ensure_serial_version_is(expected: u8, actual:
u8) -> Result<(), E
}
}
-pub(crate) fn ensure_preamble_longs_in(expected: &[u8], actual: u8) ->
Result<(), Error> {
+pub fn ensure_preamble_longs_in(expected: &[u8], actual: u8) -> Result<(),
Error> {
if expected.contains(&actual) {
Ok(())
} else {
@@ -42,7 +42,7 @@ pub(crate) fn ensure_preamble_longs_in(expected: &[u8],
actual: u8) -> Result<()
}
}
-pub(crate) fn ensure_preamble_longs_in_range(
+pub fn ensure_preamble_longs_in_range(
expected: impl RangeBounds<u8>,
actual: u8,
) -> Result<(), Error> {
diff --git a/datasketches/src/common/inv_pow2.rs
b/datasketches/src/common/inv_pow2.rs
index 353faa2..a61f1ca 100644
--- a/datasketches/src/common/inv_pow2.rs
+++ b/datasketches/src/common/inv_pow2.rs
@@ -17,7 +17,7 @@
/// Compute 1 / 2^exp using the same bit construction as DataSketches Java.
#[inline]
-pub(crate) fn inv_pow2(exp: u8) -> f64 {
+pub fn inv_pow2(exp: u8) -> f64 {
f64::from_bits((1023 - exp as u64) << 52)
}
diff --git a/datasketches/src/countmin/serialization.rs
b/datasketches/src/countmin/serialization.rs
index 4f078a9..7a930e0 100644
--- a/datasketches/src/countmin/serialization.rs
+++ b/datasketches/src/countmin/serialization.rs
@@ -15,7 +15,7 @@
// specific language governing permissions and limitations
// under the License.
-pub(super) const PREAMBLE_LONGS_SHORT: u8 = 2;
-pub(super) const SERIAL_VERSION: u8 = 1;
-pub(super) const FLAGS_IS_EMPTY: u8 = 1 << 0;
-pub(super) const LONG_SIZE_BYTES: usize = 8;
+pub const PREAMBLE_LONGS_SHORT: u8 = 2;
+pub const SERIAL_VERSION: u8 = 1;
+pub const FLAGS_IS_EMPTY: u8 = 1 << 0;
+pub const LONG_SIZE_BYTES: usize = 8;
diff --git a/datasketches/src/cpc/compression.rs
b/datasketches/src/cpc/compression.rs
index 4cefe56..71b65ff 100644
--- a/datasketches/src/cpc/compression.rs
+++ b/datasketches/src/cpc/compression.rs
@@ -24,7 +24,7 @@ use
crate::cpc::compression_data::LENGTH_LIMITED_UNARY_DECODING_TABLE65;
use crate::cpc::compression_data::LENGTH_LIMITED_UNARY_ENCODING_TABLE65;
use crate::error::Error;
-pub(super) fn encode_pairs(pairs: &[u32], lg_k: u8, output: &mut SketchBytes)
-> usize {
+pub fn encode_pairs(pairs: &[u32], lg_k: u8, output: &mut SketchBytes) ->
usize {
let num_pairs = pairs.len() as u32;
let num_base_bits =
golomb_choose_number_of_base_bits((1 << lg_k) + num_pairs,
u64::from(num_pairs));
@@ -57,12 +57,7 @@ pub(super) fn encode_pairs(pairs: &[u32], lg_k: u8, output:
&mut SketchBytes) ->
bits.finish()
}
-pub(super) fn encode_window(
- window: &[u8],
- lg_k: u8,
- num_coupons: u32,
- output: &mut SketchBytes,
-) -> usize {
+pub fn encode_window(window: &[u8], lg_k: u8, num_coupons: u32, output: &mut
SketchBytes) -> usize {
let pseudo_phase = determine_pseudo_phase(lg_k, num_coupons);
let encoding_table = &ENCODING_TABLES_FOR_HIGH_ENTROPY_BYTE[pseudo_phase
as usize];
let mut bits = BitWriter::new(output);
@@ -130,7 +125,7 @@ impl<'a> BitWriter<'a> {
}
}
-pub(super) fn decode_pairs(data: &[u8], num_pairs: u32, lg_k: u8) ->
Result<Vec<u32>, Error> {
+pub fn decode_pairs(data: &[u8], num_pairs: u32, lg_k: u8) -> Result<Vec<u32>,
Error> {
if num_pairs == 0 {
return Ok(vec![]);
}
@@ -187,7 +182,7 @@ pub(super) fn decode_pairs(data: &[u8], num_pairs: u32,
lg_k: u8) -> Result<Vec<
Ok(pairs)
}
-pub(super) fn decode_window(data: &[u8], lg_k: u8, num_coupons: u32) ->
Result<Vec<u8>, Error> {
+pub fn decode_window(data: &[u8], lg_k: u8, num_coupons: u32) ->
Result<Vec<u8>, Error> {
let mut window = vec![0; 1 << lg_k];
let pseudo_phase = determine_pseudo_phase(lg_k, num_coupons);
let decoding_table = &DECODING_TABLES_FOR_HIGH_ENTROPY_BYTE[pseudo_phase
as usize];
@@ -274,7 +269,7 @@ impl<'a> BitReader<'a> {
}
}
-pub(super) fn determine_pseudo_phase(lg_k: u8, num_coupons: u32) -> u8 {
+pub fn determine_pseudo_phase(lg_k: u8, num_coupons: u32) -> u8 {
let k = 1u64 << lg_k;
let num_coupons = u64::from(num_coupons);
// This mid-range logic produces pseudo-phases. They are used to select
encoding tables.
diff --git a/datasketches/src/cpc/compression_data.rs
b/datasketches/src/cpc/compression_data.rs
index 3c8c464..3c9923e 100644
--- a/datasketches/src/cpc/compression_data.rs
+++ b/datasketches/src/cpc/compression_data.rs
@@ -17,7 +17,7 @@
/// Notice that there are only 65 symbols here, which is different from our
usual 8->12 coding
/// scheme which handles 256 symbols.
-pub(super) static LENGTH_LIMITED_UNARY_ENCODING_TABLE65: [u16; 65] = [
+pub static LENGTH_LIMITED_UNARY_ENCODING_TABLE65: [u16; 65] = [
// Length-limited "unary" code with 65 symbols.
// entropy: 2.0
// avg_length: 2.0249023437500000000; max_length = 12; num_symbols = 65
@@ -92,7 +92,7 @@ pub(super) static LENGTH_LIMITED_UNARY_ENCODING_TABLE65:
[u16; 65] = [
];
/// Reverse mapping for the length-limited unary code with 65 symbols.
-pub(super) static LENGTH_LIMITED_UNARY_DECODING_TABLE65: [u16; 4096] = [
+pub static LENGTH_LIMITED_UNARY_DECODING_TABLE65: [u16; 4096] = [
256, 513, 256, 770, 256, 513, 256, 1027, 256, 513, 256, 770, 256, 513,
256, 1284, 256, 513,
256, 770, 256, 513, 256, 1027, 256, 513, 256, 770, 256, 513, 256, 1797,
256, 513, 256, 770,
256, 513, 256, 1027, 256, 513, 256, 770, 256, 513, 256, 1284, 256, 513,
256, 770, 256, 513,
@@ -336,7 +336,7 @@ pub(super) static LENGTH_LIMITED_UNARY_DECODING_TABLE65:
[u16; 4096] = [
/// encoding for rows containing more than one surprising bit).
///
/// These permutations were created by the ocaml program
"generatePermutationsForSLIDING.ml".
-pub(super) static COLUMN_PERMUTATIONS_FOR_ENCODING: [[u8; 56]; 16] = [
+pub static COLUMN_PERMUTATIONS_FOR_ENCODING: [[u8; 56]; 16] = [
// for phase = 1 / 32
[
0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26,
@@ -436,7 +436,7 @@ pub(super) static COLUMN_PERMUTATIONS_FOR_ENCODING: [[u8;
56]; 16] = [
];
/// Reverse mapping for column permutations.
-pub(super) static COLUMN_PERMUTATIONS_FOR_DECODING: [[u8; 56]; 16] = [
+pub static COLUMN_PERMUTATIONS_FOR_DECODING: [[u8; 56]; 16] = [
[
0, 1, 2, 3, 55, 4, 5, 6, 7, 8, 9, 10, 11, 12, 54, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 53, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44,
@@ -532,7 +532,7 @@ pub(super) static COLUMN_PERMUTATIONS_FOR_DECODING: [[u8;
56]; 16] = [
///
/// Only the encoding tables are defined by this file. The decoding tables
(which are exact
/// inverses) are created at library startup time.
-pub(super) static ENCODING_TABLES_FOR_HIGH_ENTROPY_BYTE: [[u16; 256]; 22] = [
+pub static ENCODING_TABLES_FOR_HIGH_ENTROPY_BYTE: [[u16; 256]; 22] = [
// Sixteen Encoding Tables for the Steady State.
// (table 0 of 22) (steady 0 of 16) (phase = 0.031250000 = 1.0 / 32.0)
@@ -6326,7 +6326,7 @@ pub(super) static ENCODING_TABLES_FOR_HIGH_ENTROPY_BYTE:
[[u16; 256]; 22] = [
];
/// Reverse mapping for high entropy byte encoding tables.
-pub(super) static DECODING_TABLES_FOR_HIGH_ENTROPY_BYTE: [[u16; 4096]; 22] = [
+pub static DECODING_TABLES_FOR_HIGH_ENTROPY_BYTE: [[u16; 4096]; 22] = [
[
519, 1035, 771, 1567, 519, 1293, 783, 2081, 519, 1281, 771, 1809, 519,
1303, 783, 2609,
519, 1035, 771, 1575, 519, 1299, 783, 2304, 519, 1285, 771, 1859, 519,
1545, 783, 3186,
diff --git a/datasketches/src/cpc/estimator.rs
b/datasketches/src/cpc/estimator.rs
index ef00b0b..20e9866 100644
--- a/datasketches/src/cpc/estimator.rs
+++ b/datasketches/src/cpc/estimator.rs
@@ -88,7 +88,7 @@ static HIP_HIGH_SIDE_DATA: [u16; 33] = [
5880, 5914, 5953, // 14 1000297
];
-pub(super) fn estimate(merge_flag: bool, hip_est_accum: f64, lg_k: u8,
num_coupons: u32) -> f64 {
+pub fn estimate(merge_flag: bool, hip_est_accum: f64, lg_k: u8, num_coupons:
u32) -> f64 {
if !merge_flag {
hip_est_accum
} else {
@@ -96,7 +96,7 @@ pub(super) fn estimate(merge_flag: bool, hip_est_accum: f64,
lg_k: u8, num_coupo
}
}
-pub(super) fn lower_bound(
+pub fn lower_bound(
merge_flag: bool,
hip_est_accum: f64,
lg_k: u8,
@@ -110,7 +110,7 @@ pub(super) fn lower_bound(
}
}
-pub(super) fn upper_bound(
+pub fn upper_bound(
merge_flag: bool,
hip_est_accum: f64,
lg_k: u8,
diff --git a/datasketches/src/cpc/kxp_byte_lookup.rs
b/datasketches/src/cpc/kxp_byte_lookup.rs
index 31e2185..3032c46 100644
--- a/datasketches/src/cpc/kxp_byte_lookup.rs
+++ b/datasketches/src/cpc/kxp_byte_lookup.rs
@@ -15,7 +15,7 @@
// specific language governing permissions and limitations
// under the License.
-pub(super) static KXP_BYTE_TABLE: [f64; 256] = [
+pub static KXP_BYTE_TABLE: [f64; 256] = [
0.99609375, 0.49609375, 0.74609375, 0.24609375, 0.87109375, 0.37109375,
0.62109375, 0.12109375,
0.93359375, 0.43359375, 0.68359375, 0.18359375, 0.80859375, 0.30859375,
0.55859375, 0.05859375,
0.96484375, 0.46484375, 0.71484375, 0.21484375, 0.83984375, 0.33984375,
0.58984375, 0.08984375,
diff --git a/datasketches/src/cpc/pair_table.rs
b/datasketches/src/cpc/pair_table.rs
index 8c0fb62..a476ec1 100644
--- a/datasketches/src/cpc/pair_table.rs
+++ b/datasketches/src/cpc/pair_table.rs
@@ -27,7 +27,7 @@ const DOWNSIZE_DENOMINATOR: u32 = 4;
/// This table stores `(row, col)` pairs and uses linear probing for collision
resolution. It is
/// optimized for scenarios where the cardinality of entries is low.
#[derive(Debug, Clone)]
-pub(super) struct PairTable {
+pub struct PairTable {
/// log2 of number of slots
lg_size: u8,
num_valid_bits: u8,
diff --git a/datasketches/src/cpc/serialization.rs
b/datasketches/src/cpc/serialization.rs
index 3267ec3..36d25d3 100644
--- a/datasketches/src/cpc/serialization.rs
+++ b/datasketches/src/cpc/serialization.rs
@@ -15,13 +15,13 @@
// specific language governing permissions and limitations
// under the License.
-pub(super) const SERIAL_VERSION: u8 = 1;
-pub(super) const FLAG_COMPRESSED: u8 = 1;
-pub(super) const FLAG_HAS_HIP: u8 = 2;
-pub(super) const FLAG_HAS_TABLE: u8 = 3;
-pub(super) const FLAG_HAS_WINDOW: u8 = 4;
+pub const SERIAL_VERSION: u8 = 1;
+pub const FLAG_COMPRESSED: u8 = 1;
+pub const FLAG_HAS_HIP: u8 = 2;
+pub const FLAG_HAS_TABLE: u8 = 3;
+pub const FLAG_HAS_WINDOW: u8 = 4;
-pub(super) fn make_preamble_ints(
+pub fn make_preamble_ints(
num_coupons: u32,
has_hip: bool,
has_table: bool,
diff --git a/datasketches/src/cpc/sketch.rs b/datasketches/src/cpc/sketch.rs
index 417512a..8ebaeb4 100644
--- a/datasketches/src/cpc/sketch.rs
+++ b/datasketches/src/cpc/sketch.rs
@@ -249,7 +249,7 @@ impl CpcSketch {
.expect("surprising value table must be initialized")
}
- pub(super) fn surprising_value_table_mut(&mut self) -> &mut PairTable {
+ fn surprising_value_table_mut(&mut self) -> &mut PairTable {
self.surprising_value_table
.as_mut()
.expect("surprising value table must be initialized")
diff --git a/datasketches/src/frequencies/reverse_purge_item_hash_map.rs
b/datasketches/src/frequencies/reverse_purge_item_hash_map.rs
index 4c06849..f32e9ab 100644
--- a/datasketches/src/frequencies/reverse_purge_item_hash_map.rs
+++ b/datasketches/src/frequencies/reverse_purge_item_hash_map.rs
@@ -32,7 +32,7 @@ const MAX_SAMPLE_SIZE: usize = 1024;
/// Linear-probing hash map for (item, count) pairs with reverse purge support.
#[derive(Debug, Clone)]
-pub(super) struct ReversePurgeItemHashMap<T> {
+pub struct ReversePurgeItemHashMap<T> {
lg_length: u8,
load_threshold: usize,
keys: Vec<Option<T>>,
diff --git a/datasketches/src/hash/seed.rs b/datasketches/src/hash/seed.rs
index f3a31a0..b384d8a 100644
--- a/datasketches/src/hash/seed.rs
+++ b/datasketches/src/hash/seed.rs
@@ -27,7 +27,7 @@ use crate::hash::MurmurHash3X64128;
/// # Errors
///
/// Returns an error of `error_kind` if the computed seed hash is zero.
-pub(crate) fn compute_seed_hash(seed: u64, error_kind: ErrorKind) ->
Result<u16, Error> {
+pub fn compute_seed_hash(seed: u64, error_kind: ErrorKind) -> Result<u16,
Error> {
use std::hash::Hasher;
let mut hasher = MurmurHash3X64128::with_seed(0);
@@ -44,7 +44,7 @@ pub(crate) fn compute_seed_hash(seed: u64, error_kind:
ErrorKind) -> Result<u16,
}
/// Checks that an actual seed hash matches the expected seed hash.
-pub(crate) fn check_seed_hash(
+pub fn check_seed_hash(
expected: u16,
actual: u16,
name: &'static str,
diff --git a/datasketches/src/hll/array4.rs b/datasketches/src/hll/array4.rs
index a076aa1..a117560 100644
--- a/datasketches/src/hll/array4.rs
+++ b/datasketches/src/hll/array4.rs
@@ -43,13 +43,13 @@ use crate::hll::serialization::encode_mode_byte;
const AUX_TOKEN: u8 = 15;
#[derive(Clone, Copy)]
-pub(super) enum AuxFormat {
+pub enum AuxFormat {
Compact,
Updatable { lg_arr: u8 },
}
impl AuxFormat {
- pub(super) fn from_header(compact: bool, lg_arr: u8) -> Self {
+ pub fn from_header(compact: bool, lg_arr: u8) -> Self {
if compact {
Self::Compact
} else {
@@ -106,7 +106,7 @@ impl Array4 {
/// Returns the true register value:
/// * If raw < 15: value = cur_min + raw
/// * If raw == 15 (AUX_TOKEN): value is in aux_map
- pub(super) fn get(&self, slot: u32) -> u8 {
+ pub fn get(&self, slot: u32) -> u8 {
let raw = self.get_raw(slot);
if raw < AUX_TOKEN {
@@ -121,12 +121,12 @@ impl Array4 {
}
/// Get the number of registers (K = 2^lg_config_k)
- pub(super) fn num_registers(&self) -> usize {
+ pub fn num_registers(&self) -> usize {
1 << self.lg_config_k
}
/// Returns the estimate state independently from register-derived cached
values.
- pub(super) fn estimate_state(&self) -> EstimateState {
+ pub fn estimate_state(&self) -> EstimateState {
self.estimator.estimate_state()
}
@@ -298,7 +298,7 @@ impl Array4 {
}
/// Restores estimate state after copying or transforming the same logical
sketch.
- pub(super) fn restore_estimate_state(&mut self, state: EstimateState) {
+ pub fn restore_estimate_state(&mut self, state: EstimateState) {
self.estimator.restore_estimate_state(state);
}
diff --git a/datasketches/src/hll/array6.rs b/datasketches/src/hll/array6.rs
index 5ab5657..70c519f 100644
--- a/datasketches/src/hll/array6.rs
+++ b/datasketches/src/hll/array6.rs
@@ -82,17 +82,17 @@ impl Array6 {
/// Get the unpacked 6-bit value (0-63) at the given slot
#[inline]
- pub(super) fn get(&self, slot: u32) -> u8 {
+ pub fn get(&self, slot: u32) -> u8 {
self.get_raw(slot)
}
/// Get the number of registers (K = 2^lg_config_k)
- pub(super) fn num_registers(&self) -> usize {
+ pub fn num_registers(&self) -> usize {
1 << self.lg_config_k
}
/// Returns the estimate state independently from register-derived cached
values.
- pub(super) fn estimate_state(&self) -> EstimateState {
+ pub fn estimate_state(&self) -> EstimateState {
self.estimator.estimate_state()
}
@@ -164,7 +164,7 @@ impl Array6 {
}
/// Restores estimate state after copying or transforming the same logical
sketch.
- pub(super) fn restore_estimate_state(&mut self, state: EstimateState) {
+ pub fn restore_estimate_state(&mut self, state: EstimateState) {
self.estimator.restore_estimate_state(state);
}
diff --git a/datasketches/src/hll/array8.rs b/datasketches/src/hll/array8.rs
index 8a3b61c..5675640 100644
--- a/datasketches/src/hll/array8.rs
+++ b/datasketches/src/hll/array8.rs
@@ -123,22 +123,22 @@ impl Array8 {
}
/// Get read access to register values (one byte per register)
- pub(super) fn values(&self) -> &[u8] {
+ pub fn values(&self) -> &[u8] {
&self.bytes
}
/// Get the number of registers (K = 2^lg_config_k)
- pub(super) fn num_registers(&self) -> usize {
+ pub fn num_registers(&self) -> usize {
1 << self.lg_config_k
}
/// Returns the estimate state independently from register-derived cached
values.
- pub(super) fn estimate_state(&self) -> EstimateState {
+ pub fn estimate_state(&self) -> EstimateState {
self.estimator.estimate_state()
}
/// Restores estimate state after copying or transforming the same logical
sketch.
- pub(super) fn restore_estimate_state(&mut self, state: EstimateState) {
+ pub fn restore_estimate_state(&mut self, state: EstimateState) {
self.estimator.restore_estimate_state(state);
}
@@ -146,7 +146,7 @@ impl Array8 {
///
/// This bypasses the normal update path and directly modifies the
register.
/// Caller must call rebuild_estimator_from_registers() after all
modifications.
- pub(super) fn set_register(&mut self, slot: usize, value: u8) {
+ pub fn set_register(&mut self, slot: usize, value: u8) {
self.bytes[slot] = value;
}
@@ -154,7 +154,7 @@ impl Array8 {
///
/// Recomputes num_zeros, kxq0, and kxq1, then switches to composite
estimation.
/// Should be called after bulk register modifications.
- pub(super) fn rebuild_estimator_from_registers(&mut self) {
+ pub fn rebuild_estimator_from_registers(&mut self) {
self.rebuild_cached_values();
self.estimator.invalidate_hip();
}
@@ -167,7 +167,7 @@ impl Array8 {
/// # Panics
///
/// Panics if src length doesn't match self length (different lg_k).
- pub(super) fn merge_array_same_lgk(&mut self, src: &[u8]) {
+ pub fn merge_array_same_lgk(&mut self, src: &[u8]) {
assert_eq!(
src.len(),
self.bytes.len(),
@@ -198,7 +198,7 @@ impl Array8 {
/// # Panics
///
/// Panics if src_lg_k <= self.lg_config_k (not downsampling).
- pub(super) fn merge_array_with_downsample(&mut self, src: &[u8], src_lg_k:
u8) {
+ pub fn merge_array_with_downsample(&mut self, src: &[u8], src_lg_k: u8) {
assert!(
src_lg_k > self.lg_config_k,
"Source lg_k must be greater than destination lg_k for
downsampling"
diff --git a/datasketches/src/hll/estimator.rs
b/datasketches/src/hll/estimator.rs
index f607e8e..8897516 100644
--- a/datasketches/src/hll/estimator.rs
+++ b/datasketches/src/hll/estimator.rs
@@ -28,7 +28,7 @@ use crate::hll::harmonic_numbers;
/// Selects the estimate that is valid for the current register history.
#[derive(Debug, Clone, Copy, PartialEq)]
-pub(super) enum EstimateState {
+pub enum EstimateState {
/// The register updates have a known order, so the HIP accumulator is
valid.
Hip(f64),
/// A bulk merge lost the update order, so the estimate must come from the
registers.
@@ -61,12 +61,7 @@ impl Estimator {
}
/// Restores estimator fields from an HLL serialization preamble.
- pub(super) fn from_serialized(
- hip_accum: f64,
- kxq0: f64,
- kxq1: f64,
- out_of_order: bool,
- ) -> Self {
+ pub fn from_serialized(hip_accum: f64, kxq0: f64, kxq1: f64, out_of_order:
bool) -> Self {
let estimate_state = if out_of_order {
EstimateState::Composite
} else {
@@ -325,22 +320,22 @@ impl Estimator {
}
/// Returns the estimate state independently from register-derived KxQ
values.
- pub(super) fn estimate_state(&self) -> EstimateState {
+ pub fn estimate_state(&self) -> EstimateState {
self.estimate_state
}
/// Restores estimate state after copying or transforming the same logical
sketch.
- pub(super) fn restore_estimate_state(&mut self, state: EstimateState) {
+ pub fn restore_estimate_state(&mut self, state: EstimateState) {
self.estimate_state = state;
}
/// Invalidates HIP after registers from independent histories are merged.
- pub(super) fn invalidate_hip(&mut self) {
+ pub fn invalidate_hip(&mut self) {
self.estimate_state = EstimateState::Composite;
}
/// Replaces register-derived KxQ values after a bulk register operation.
- pub(super) fn restore_kxq(&mut self, kxq0: f64, kxq1: f64) {
+ pub fn restore_kxq(&mut self, kxq0: f64, kxq1: f64) {
self.kxq0 = kxq0;
self.kxq1 = kxq1;
}
diff --git a/datasketches/src/req/compactor.rs
b/datasketches/src/req/compactor.rs
index e4835dc..a81acf7 100644
--- a/datasketches/src/req/compactor.rs
+++ b/datasketches/src/req/compactor.rs
@@ -33,7 +33,7 @@ use crate::req::value::ReqValue;
/// When the compactor reaches its nominal capacity, it performs compaction
/// by keeping approximately half the items and promoting the rest to the next
level.
#[derive(Debug, Clone)]
-pub(super) struct Compactor<T> {
+pub struct Compactor<T> {
/// Current items in the compactor
items: Vec<T>,
/// Whether items are currently sorted
@@ -68,7 +68,7 @@ where
/// * `lg_weight` - The level (log weight) of this compactor
/// * `k` - The k parameter from the parent sketch
/// * `rank_accuracy` - Rank accuracy configuration
- pub(super) fn new(lg_weight: u8, k: u16, rank_accuracy: RankAccuracy) ->
Self {
+ pub fn new(lg_weight: u8, k: u16, rank_accuracy: RankAccuracy) -> Self {
let section_size_raw = k as f32;
let section_size = nearest_even_section_size(section_size_raw);
let num_sections = INITIAL_SECTIONS_PER_COMPACTOR;
@@ -92,23 +92,23 @@ where
}
/// Returns the number of items currently in this compactor.
- pub(super) fn num_items(&self) -> u32 {
+ pub fn num_items(&self) -> u32 {
self.items.len() as u32
}
/// Returns the nominal capacity of this compactor.
- pub(super) fn nominal_capacity(&self) -> u32 {
+ pub fn nominal_capacity(&self) -> u32 {
2 * self.section_size * self.num_sections as u32
}
/// Returns whether the items are currently sorted.
- pub(super) fn is_sorted(&self) -> bool {
+ pub fn is_sorted(&self) -> bool {
self.is_sorted
}
/// Appends an item to this compactor.
#[inline(always)]
- pub(super) fn append(&mut self, item: T) {
+ pub fn append(&mut self, item: T) {
self.items.push(item);
if self.items.len() > 1 {
self.is_sorted = false;
@@ -116,7 +116,7 @@ where
}
/// Merges items from another compactor into this one.
- pub(super) fn merge(&mut self, other: &Self) {
+ pub fn merge(&mut self, other: &Self) {
debug_assert_eq!(self.lg_weight, other.lg_weight);
self.state |= other.state;
if !other.items.is_empty() {
@@ -140,7 +140,7 @@ where
/// Uses binary search when this compactor is sorted, and a linear scan
/// otherwise. This lets [`ReqSketch::rank`](crate::req::ReqSketch::rank)
sum
/// per-level weights directly without first building a sorted view.
- pub(super) fn count_below(&self, item: &T, inclusive: bool) -> usize {
+ pub fn count_below(&self, item: &T, inclusive: bool) -> usize {
if self.is_sorted {
if inclusive {
self.items.partition_point(|x| x <= item)
@@ -159,7 +159,7 @@ where
/// Merges sorted items into this compactor using scratch buffer to avoid
allocation.
/// Both this compactor's items and the input must be sorted.
#[inline(always)]
- pub(super) fn merge_sorted(&mut self, items: &[T]) {
+ pub fn merge_sorted(&mut self, items: &[T]) {
if items.is_empty() {
return;
}
@@ -208,7 +208,7 @@ where
/// Sorts the items in this compactor if not already sorted.
#[inline(always)]
- pub(super) fn sort(&mut self) {
+ pub fn sort(&mut self) {
if !self.is_sorted {
// Use unstable sort for better performance (stable not needed for
REQ sketch)
self.items.sort_unstable();
@@ -220,7 +220,7 @@ where
/// Writes promoted items into `out` and removes the compacted range
in-place via `copy_within +
/// truncate`.
#[inline(always)]
- pub(super) fn compact_into(&mut self, _rank_accuracy: RankAccuracy, out:
&mut Vec<T>) {
+ pub fn compact_into(&mut self, _rank_accuracy: RankAccuracy, out: &mut
Vec<T>) {
if self.items.is_empty() {
out.clear();
return;
@@ -271,17 +271,17 @@ where
}
/// Returns an iterator over the items in this compactor.
- pub(super) fn iter(&self) -> impl Iterator<Item = &T> {
+ pub fn iter(&self) -> impl Iterator<Item = &T> {
self.items.iter()
}
/// Returns a slice of items for zero-allocation iteration.
- pub(super) fn items_slice(&self) -> &[T] {
+ pub fn items_slice(&self) -> &[T] {
&self.items
}
/// Returns the weight (2^lg_weight) for items in this compactor.
- pub(super) fn weight(&self) -> u64 {
+ pub fn weight(&self) -> u64 {
1u64 << self.lg_weight
}
@@ -349,7 +349,7 @@ where
}
/// Serialize this compactor (preamble + items) into the byte buffer.
- pub(super) fn serialize_into(&self, bytes: &mut crate::codec::SketchBytes)
+ pub fn serialize_into(&self, bytes: &mut crate::codec::SketchBytes)
where
T: ReqValue,
{
@@ -365,7 +365,7 @@ where
}
/// Deserialize a compactor (preamble + items) from the byte cursor.
- pub(super) fn deserialize(
+ pub fn deserialize(
cursor: &mut crate::codec::SketchSlice<'_>,
k: u16,
expected_lg_weight: u8,
@@ -432,7 +432,7 @@ where
/// helper synthesises a fresh compactor and seeds it with the
deserialized items.
/// A false wire flag stays false for byte-stable C++/Java round trips; a
true flag
/// is cleared if the items are not actually sorted.
- pub(super) fn raw_items_compactor(
+ pub fn raw_items_compactor(
k: u16,
rank_accuracy: RankAccuracy,
items: Vec<T>,
@@ -451,7 +451,7 @@ where
/// buffer) is reset; the deterministic `state` counter and the persistent
/// configuration (`lg_weight`, `section_size_raw`, `num_sections`) are
preserved
/// from the wire data.
- pub(super) fn from_serialized_state(
+ fn from_serialized_state(
lg_weight: u8,
section_size_raw: f32,
num_sections: u8,
@@ -475,22 +475,6 @@ where
}
}
-#[cfg(test)]
-impl<T> Compactor<T>
-where
- T: Clone + Ord,
-{
- /// Returns the level (log weight) of this compactor. Test-only accessor.
- pub(super) fn lg_weight(&self) -> u8 {
- self.lg_weight
- }
-
- /// Returns the current state for deterministic compaction. Test-only
accessor.
- pub(super) fn state(&self) -> u64 {
- self.state
- }
-}
-
#[cfg(test)]
mod tests {
use googletest::assert_that;
@@ -502,7 +486,7 @@ mod tests {
#[test]
fn test_new_compactor() {
let compactor: Compactor<i32> = Compactor::new(0, 12,
RankAccuracy::HighRank);
- assert_eq!(compactor.lg_weight(), 0);
+ assert_eq!(compactor.lg_weight, 0);
assert_eq!(compactor.num_items(), 0);
assert!(compactor.is_sorted());
assert_eq!(compactor.weight(), 1);
@@ -582,8 +566,8 @@ mod tests {
.unwrap();
assert_eq!(c.num_items(), c2.num_items());
- assert_eq!(c.lg_weight(), c2.lg_weight());
- assert_eq!(c.state(), c2.state());
+ assert_eq!(c.lg_weight, c2.lg_weight);
+ assert_eq!(c.state, c2.state);
let xs: Vec<ReqFloat<f32>> = c.iter().copied().collect();
let ys: Vec<ReqFloat<f32>> = c2.iter().copied().collect();
assert_eq!(xs, ys);
diff --git a/datasketches/src/req/serialization.rs
b/datasketches/src/req/serialization.rs
index 2d56a5e..90c949a 100644
--- a/datasketches/src/req/serialization.rs
+++ b/datasketches/src/req/serialization.rs
@@ -24,17 +24,17 @@ use crate::req::INITIAL_SECTIONS_PER_COMPACTOR;
use crate::req::MIN_K;
use crate::req::nearest_even_section_size;
-pub(super) const SERIAL_VERSION: u8 = 1;
-pub(super) const PREAMBLE_INTS_EXACT: u8 = 2;
-pub(super) const PREAMBLE_INTS_ESTIMATION: u8 = 4;
-pub(super) const RAW_ITEMS_THRESHOLD: u64 = 4;
+pub const SERIAL_VERSION: u8 = 1;
+pub const PREAMBLE_INTS_EXACT: u8 = 2;
+pub const PREAMBLE_INTS_ESTIMATION: u8 = 4;
+pub const RAW_ITEMS_THRESHOLD: u64 = 4;
/// Flag bits — match the C++ enum order: RESERVED1, RESERVED2, IS_EMPTY,
IS_HIGH_RANK, RAW_ITEMS,
/// IS_LEVEL_ZERO_SORTED.
-pub(super) const FLAG_IS_EMPTY: u8 = 1 << 2;
-pub(super) const FLAG_IS_HIGH_RANK: u8 = 1 << 3;
-pub(super) const FLAG_RAW_ITEMS: u8 = 1 << 4;
-pub(super) const FLAG_IS_LEVEL_ZERO_SORTED: u8 = 1 << 5;
+pub const FLAG_IS_EMPTY: u8 = 1 << 2;
+pub const FLAG_IS_HIGH_RANK: u8 = 1 << 3;
+pub const FLAG_RAW_ITEMS: u8 = 1 << 4;
+pub const FLAG_IS_LEVEL_ZERO_SORTED: u8 = 1 << 5;
fn section_growth_threshold(num_sections: u8) -> Option<u64> {
num_sections
@@ -59,7 +59,7 @@ fn has_reachable_section_count(state: u64, num_sections: u8)
-> bool {
sections == num_sections
}
-pub(super) fn validate_compactor_state(
+pub fn validate_compactor_state(
k: u16,
expected_lg_weight: u8,
state: u64,
@@ -84,11 +84,11 @@ pub(super) fn validate_compactor_state(
Ok(())
}
-pub(super) fn check_serial_version(actual: u8) -> Result<(), Error> {
+pub fn check_serial_version(actual: u8) -> Result<(), Error> {
ensure_serial_version_is(SERIAL_VERSION, actual)
}
-pub(super) fn check_preamble_ints(actual: u8, num_levels: u8) -> Result<(),
Error> {
+pub fn check_preamble_ints(actual: u8, num_levels: u8) -> Result<(), Error> {
let expected = if num_levels > 1 {
PREAMBLE_INTS_ESTIMATION
} else {
diff --git a/datasketches/src/req/sketch.rs b/datasketches/src/req/sketch.rs
index 1a2e263..e2f1d94 100644
--- a/datasketches/src/req/sketch.rs
+++ b/datasketches/src/req/sketch.rs
@@ -470,7 +470,7 @@ where
.sum()
}
- pub(super) fn flags_byte(&self) -> u8 {
+ fn flags_byte(&self) -> u8 {
let mut flags = 0u8;
if self.is_empty() {
flags |= FLAG_IS_EMPTY;
@@ -487,7 +487,7 @@ where
flags
}
- pub(super) fn is_raw_items(&self) -> bool {
+ fn is_raw_items(&self) -> bool {
self.n <= RAW_ITEMS_THRESHOLD && self.compactors.len() == 1
}
diff --git a/datasketches/src/tdigest/serialization.rs
b/datasketches/src/tdigest/serialization.rs
index 407e2ac..debe678 100644
--- a/datasketches/src/tdigest/serialization.rs
+++ b/datasketches/src/tdigest/serialization.rs
@@ -15,13 +15,13 @@
// specific language governing permissions and limitations
// under the License.
-pub(super) const PREAMBLE_LONGS_EMPTY_OR_SINGLE: u8 = 1;
-pub(super) const PREAMBLE_LONGS_MULTIPLE: u8 = 2;
-pub(super) const SERIAL_VERSION: u8 = 1;
-pub(super) const FLAGS_IS_EMPTY: u8 = 1 << 0;
-pub(super) const FLAGS_IS_SINGLE_VALUE: u8 = 1 << 1;
-pub(super) const FLAGS_REVERSE_MERGE: u8 = 1 << 2;
+pub const PREAMBLE_LONGS_EMPTY_OR_SINGLE: u8 = 1;
+pub const PREAMBLE_LONGS_MULTIPLE: u8 = 2;
+pub const SERIAL_VERSION: u8 = 1;
+pub const FLAGS_IS_EMPTY: u8 = 1 << 0;
+pub const FLAGS_IS_SINGLE_VALUE: u8 = 1 << 1;
+pub const FLAGS_REVERSE_MERGE: u8 = 1 << 2;
/// the format of the reference implementation is using double (f64) precision
-pub(super) const COMPAT_DOUBLE: u32 = 1;
+pub const COMPAT_DOUBLE: u32 = 1;
/// the format of the reference implementation is using float (f32) precision
-pub(super) const COMPAT_FLOAT: u32 = 2;
+pub const COMPAT_FLOAT: u32 = 2;
diff --git a/datasketches/src/tdigest/sketch.rs
b/datasketches/src/tdigest/sketch.rs
index 19f8bf3..bd27a4c 100644
--- a/datasketches/src/tdigest/sketch.rs
+++ b/datasketches/src/tdigest/sketch.rs
@@ -1544,15 +1544,15 @@ fn checked_weight_sum(total_weight: u64, weight: u64)
-> Result<u64, Error> {
///
/// Corresponds to K_2 in the reference implementation
mod scale_function {
- pub(super) fn max(q: f64, normalizer: f64) -> f64 {
+ pub fn max(q: f64, normalizer: f64) -> f64 {
q * (1. - q) / normalizer
}
- pub(super) fn normalizer(compression: f64, n: f64) -> f64 {
+ pub fn normalizer(compression: f64, n: f64) -> f64 {
compression / z(compression, n)
}
- pub(super) fn z(compression: f64, n: f64) -> f64 {
+ pub fn z(compression: f64, n: f64) -> f64 {
4. * (n / compression).ln() + 24.
}
}
diff --git a/datasketches/src/thetafamily/theta/bit_pack.rs
b/datasketches/src/thetafamily/theta/bit_pack.rs
index d64e59e..7096bbc 100644
--- a/datasketches/src/thetafamily/theta/bit_pack.rs
+++ b/datasketches/src/thetafamily/theta/bit_pack.rs
@@ -15,7 +15,7 @@
// specific language governing permissions and limitations
// under the License.
-pub(super) const BLOCK_WIDTH: usize = 8;
+pub const BLOCK_WIDTH: usize = 8;
#[inline]
fn low_bit_to_byte_mask(bits: u8) -> u8 {
@@ -33,7 +33,7 @@ fn low_bit_to_byte_mask(bits: u8) -> u8 {
/// Panics if the buffer is too small to hold the packed values.
/// The caller must ensure that `bytes` has enough capacity for
/// the total number of bits to be packed.
-pub(super) struct BitPacker<'a> {
+pub struct BitPacker<'a> {
bytes: &'a mut [u8],
byte_index: usize,
byte_bit_used: u8,
@@ -104,7 +104,7 @@ impl<'a> BitPacker<'a> {
/// Panics if the buffer is too small to provide the requested bits.
/// The caller must ensure that `bytes` has enough capacity for
/// the total number of bits to be unpacked.
-pub(super) struct BitUnpacker<'a> {
+pub struct BitUnpacker<'a> {
bytes: &'a [u8],
byte_index: usize,
byte_bit_used: u8,
@@ -4965,7 +4965,7 @@ fn unpack_bits_63(values: &mut [u64], bytes: &[u8]) {
/// * Panics if `values.len()` is not equal to `BLOCK_WIDTH`.
/// * Panics if `bits` is not in the range `1..=63`.
/// * Panics if `bytes.len()` is less than `bits`.
-pub(super) fn pack_bits_block(values: &[u64], bytes: &mut [u8], bits: u8) {
+pub fn pack_bits_block(values: &[u64], bytes: &mut [u8], bits: u8) {
assert_eq!(values.len(), BLOCK_WIDTH, "values length must be 8");
assert!(
(1..=63).contains(&bits),
@@ -5048,7 +5048,7 @@ pub(super) fn pack_bits_block(values: &[u64], bytes: &mut
[u8], bits: u8) {
/// * Panics if `values.len()` is not equal to `BLOCK_WIDTH`.
/// * Panics if `bits` is not in the range `1..=63`.
/// * Panics if `bytes.len()` is less than `bits`.
-pub(super) fn unpack_bits_block(values: &mut [u64], bytes: &[u8], bits: u8) {
+pub fn unpack_bits_block(values: &mut [u64], bytes: &[u8], bits: u8) {
assert_eq!(values.len(), BLOCK_WIDTH, "values length must be 8");
assert!(
(1..=63).contains(&bits),
diff --git a/datasketches/src/thetafamily/theta/hash_table.rs
b/datasketches/src/thetafamily/theta/hash_table.rs
index 6cd1735..3c96b3c 100644
--- a/datasketches/src/thetafamily/theta/hash_table.rs
+++ b/datasketches/src/thetafamily/theta/hash_table.rs
@@ -28,7 +28,7 @@ use crate::thetacommon::hash_table::SketchHashTable;
/// * After it reaches the capacity bigger than 2^lg_nom_size, every time the
number of entries
/// exceeds the threshold, it will rebuild the table: only keep the min
2^lg_nom_size entries and
/// update the theta to the k-th smallest entry.
-pub(super) type ThetaHashTable = SketchHashTable<ThetaEntry>;
+pub type ThetaHashTable = SketchHashTable<ThetaEntry>;
/// A retained entry in a Theta sketch.
#[derive(Debug, Clone, Copy)]
diff --git a/datasketches/src/thetafamily/theta/serialization.rs
b/datasketches/src/thetafamily/theta/serialization.rs
index 54ba181..f9d6e2c 100644
--- a/datasketches/src/thetafamily/theta/serialization.rs
+++ b/datasketches/src/thetafamily/theta/serialization.rs
@@ -17,9 +17,9 @@
//! Binary serialization format constants for Theta sketches.
-pub(super) const UNCOMPRESSED_SERIAL_VERSION: u8 = 3;
-pub(super) const COMPRESSED_SERIAL_VERSION: u8 = 4;
+pub const UNCOMPRESSED_SERIAL_VERSION: u8 = 3;
+pub const COMPRESSED_SERIAL_VERSION: u8 = 4;
-pub(super) const V2_PREAMBLE_EMPTY: u8 = 1;
-pub(super) const V2_PREAMBLE_PRECISE: u8 = 2;
-pub(super) const V2_PREAMBLE_ESTIMATE: u8 = 3;
+pub const V2_PREAMBLE_EMPTY: u8 = 1;
+pub const V2_PREAMBLE_PRECISE: u8 = 2;
+pub const V2_PREAMBLE_ESTIMATE: u8 = 3;
diff --git a/datasketches/src/thetafamily/tuple/hash_table.rs
b/datasketches/src/thetafamily/tuple/hash_table.rs
index 04b26f6..638d0c7 100644
--- a/datasketches/src/thetafamily/tuple/hash_table.rs
+++ b/datasketches/src/thetafamily/tuple/hash_table.rs
@@ -61,7 +61,7 @@ impl<S> TupleEntry<S> {
/// This is the Theta sketch hash table extended so that each retained key
carries a user-defined
/// summary. Unlike the Theta hash table, when a key is inserted that already
exists, the incoming
/// update is merged into the existing summary rather than discarded.
-pub(super) type TupleHashTable<S> = SketchHashTable<TupleEntry<S>>;
+pub type TupleHashTable<S> = SketchHashTable<TupleEntry<S>>;
impl<S> SketchEntry for TupleEntry<S> {
fn hash(&self) -> u64 {
diff --git a/datasketches/src/thetafamily/tuple/serialization.rs
b/datasketches/src/thetafamily/tuple/serialization.rs
index 5798883..b077f0c 100644
--- a/datasketches/src/thetafamily/tuple/serialization.rs
+++ b/datasketches/src/thetafamily/tuple/serialization.rs
@@ -30,14 +30,14 @@ use crate::codec::SketchSlice;
use crate::error::Error;
/// Current serial version written by this implementation.
-pub(super) const SERIAL_VERSION: u8 = 3;
+pub const SERIAL_VERSION: u8 = 3;
/// Legacy serial version still accepted on read.
-pub(super) const SERIAL_VERSION_LEGACY: u8 = 1;
+pub const SERIAL_VERSION_LEGACY: u8 = 1;
/// Current sketch-type byte written by this implementation.
-pub(super) const SKETCH_TYPE: u8 = 1;
+pub const SKETCH_TYPE: u8 = 1;
/// Legacy sketch-type byte still accepted on read.
-pub(super) const SKETCH_TYPE_LEGACY: u8 = 5;
+pub const SKETCH_TYPE_LEGACY: u8 = 5;
/// Trait for values that can be stored as Tuple sketch summaries.
///
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]