diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4942e6e..4b2e84e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,6 +60,12 @@ Lint: cargo x lint ``` +## Public API documentation + +- Describe types with noun phrases and API behavior with third-person present-tense verbs such as `Creates`, `Updates`, and `Returns`. +- 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. + ## Integration test layout Integration tests for the `datasketches` crate live under `datasketches/tests` and use two entry-point patterns. diff --git a/datasketches/src/bloom/builder.rs b/datasketches/src/bloom/builder.rs index 67f62b2..6fece08 100644 --- a/datasketches/src/bloom/builder.rs +++ b/datasketches/src/bloom/builder.rs @@ -52,12 +52,12 @@ impl BloomFilterBuilder { /// /// # Arguments /// - /// * `max_items`: Maximum expected number of distinct items - /// * `fpp`: Target false positive probability (e.g., 0.01 for 1%) + /// * `max_items`: Maximum expected number of distinct items. + /// * `fpp`: Target false positive probability (for example, `0.01` for `1%`). /// /// # Panics /// - /// Panics if `max_items` is 0 or `fpp` is not in (0.0, 1.0]. + /// Panics if `max_items` is `0` or `fpp` is outside `(0.0, 1.0]`. /// /// # Examples /// @@ -96,14 +96,14 @@ impl BloomFilterBuilder { /// /// # Arguments /// - /// * `num_bits`: Total number of bits in the filter - /// * `num_hashes`: Number of hash functions to use + /// * `num_bits`: Total number of bits in the filter. + /// * `num_hashes`: Number of hash functions to use. /// /// # Panics /// /// Panics if any of: - /// * `num_bits` < [`Self::MIN_NUM_BITS`] or `num_bits` > [`Self::MAX_NUM_BITS`] - /// * `num_hashes` < [`Self::MIN_NUM_HASHES`] or `num_hashes` > [`Self::MAX_NUM_HASHES`] + /// * `num_bits < Self::MIN_NUM_BITS` or `num_bits > Self::MAX_NUM_BITS`. + /// * `num_hashes < Self::MIN_NUM_HASHES` or `num_hashes > Self::MAX_NUM_HASHES`. /// /// # Examples /// diff --git a/datasketches/src/bloom/sketch.rs b/datasketches/src/bloom/sketch.rs index 8b0543f..e8734e7 100644 --- a/datasketches/src/bloom/sketch.rs +++ b/datasketches/src/bloom/sketch.rs @@ -52,11 +52,10 @@ pub struct BloomFilter { } impl BloomFilter { - /// Tests whether an item is possibly in the set. + /// Returns `true` if an item is possibly in the set. /// - /// Returns: - /// * `true`: Item was **possibly** inserted (or false positive) - /// * `false`: Item was **definitely not** inserted + /// A `false` result means the item was definitely not inserted; a `true` result may be a false + /// positive. /// /// # Examples /// @@ -78,9 +77,8 @@ impl BloomFilter { self.check_bits(h0, h1) } - /// Tests and inserts an item in a single operation. + /// Returns `true` if an item was possibly present before inserting it. /// - /// Returns whether the item was possibly already in the set before insertion. /// This is more efficient than calling `contains()` then `insert()` separately. /// /// # Examples @@ -294,7 +292,7 @@ impl BloomFilter { self.num_bits_set as f64 / self.capacity() as f64 } - /// Estimates the current false positive probability. + /// Returns the estimated current false positive probability. /// /// Uses the approximation: `load_factor^k` /// where: @@ -312,7 +310,7 @@ impl BloomFilter { load.powf(k) } - /// Checks if two filters are compatible for merging. + /// Returns `true` if two filters are compatible for merging. /// /// Filters are compatible if they have the same: /// * Capacity (number of bits) @@ -389,9 +387,9 @@ impl BloomFilter { /// # Errors /// /// Returns an error if: - /// * The data is truncated or corrupted - /// * The family ID doesn't match (not a Bloom filter) - /// * The serial version is unsupported + /// * The data is truncated or corrupted. + /// * The family ID does not identify a Bloom filter. + /// * The serial version is unsupported. /// /// # Examples /// @@ -572,7 +570,7 @@ impl BloomFilter { } } - /// Returns the estimated size of the filter in bytes + /// Returns the estimated size of the filter in bytes. pub fn estimated_size(&self) -> usize { size_of::() + self.bit_array.len() * size_of::() } diff --git a/datasketches/src/codec/encode.rs b/datasketches/src/codec/encode.rs index 60e85c8..20ac0ea 100644 --- a/datasketches/src/codec/encode.rs +++ b/datasketches/src/codec/encode.rs @@ -21,14 +21,14 @@ pub struct SketchBytes { } impl SketchBytes { - /// Constructs an empty `SketchBytes` with at least the specified capacity. + /// Creates an empty `SketchBytes` with at least the specified capacity. pub fn with_capacity(capacity: usize) -> Self { Self { bytes: Vec::with_capacity(capacity), } } - /// Consumes the `SketchBytes` and returns the underlying `Vec`. + /// Returns the underlying `Vec`, consuming the `SketchBytes`. pub fn into_bytes(self) -> Vec { self.bytes } diff --git a/datasketches/src/common/num_std_dev.rs b/datasketches/src/common/num_std_dev.rs index 441a07b..2aa908f 100644 --- a/datasketches/src/common/num_std_dev.rs +++ b/datasketches/src/common/num_std_dev.rs @@ -28,7 +28,7 @@ static DELTA_OF_NUM_STD_DEVS: [f64; 4] = [ 0.0013498126861731796, // = 0.5 (1 + erf((-3/sqrt(2)))) ]; -/// Number of standard deviations for confidence bounds +/// Number of standard deviations for confidence bounds. /// /// This enum specifies the number of standard deviations to use when computing /// upper and lower bounds for cardinality estimates. Higher values provide wider @@ -37,21 +37,21 @@ static DELTA_OF_NUM_STD_DEVS: [f64; 4] = [ #[repr(u8)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum NumStdDev { - /// One standard deviation (\~68% confidence interval) + /// One standard deviation (\~68% confidence interval). One = 1, - /// Two standard deviations (\~95% confidence interval) + /// Two standard deviations (\~95% confidence interval). Two = 2, - /// Three standard deviations (\~99.7% confidence interval) + /// Three standard deviations (\~99.7% confidence interval). Three = 3, } impl NumStdDev { - /// Returns the tail probability (delta) for this confidence level + /// Returns the tail probability (delta) for this confidence level. pub const fn tail_probability(&self) -> f64 { DELTA_OF_NUM_STD_DEVS[*self as usize] } - /// Returns the number of standard deviations as an `u8`. + /// Returns the number of standard deviations as a `u8`. pub const fn as_u8(&self) -> u8 { *self as u8 } diff --git a/datasketches/src/common/resize.rs b/datasketches/src/common/resize.rs index 5fa4742..60e41f7 100644 --- a/datasketches/src/common/resize.rs +++ b/datasketches/src/common/resize.rs @@ -15,23 +15,22 @@ // specific language governing permissions and limitations // under the License. -/// For the Families that accept this configuration parameter, it controls the size multiple that -/// affects how fast the internal cache grows, when more space is required. +/// Controls internal cache growth for sketch families that support resizing. /// -/// For Theta Sketches, the Resize Factor is a dynamic, speed performance vs. memory size tradeoff. -/// The sketches created on-heap and configured with a Resize Factor of > X1 start out with an -/// internal hash table size that is the smallest submultiple of the target Nominal Entries +/// For Theta sketches, the resize factor provides a dynamic trade-off between update speed and +/// memory use. Sketches configured with a resize factor greater than `X1` start with an internal +/// hash table size that is the smallest submultiple of the target nominal entries /// and larger than the minimum required hash table size for that sketch. /// -/// When the sketch needs to be resized larger, then the Resize Factor is used as a multiplier of +/// When the sketch needs to grow, the resize factor is used as a multiplier for /// the current sketch cache array size. /// -/// "X1" means no resizing is allowed and the sketch will be initialized at full size. +/// `X1` means no resizing is allowed and the sketch will be initialized at full size. /// -/// "X2" means the internal cache will start very small and double in size until the target size is +/// `X2` means the internal cache will start very small and double in size until the target size is /// reached. /// -/// Similarly, "X4" is a factor of 4 and "X8" is a factor of 8. +/// Similarly, `X4` is a factor of `4` and `X8` is a factor of `8`. /// /// # Examples /// @@ -44,18 +43,18 @@ /// ``` #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ResizeFactor { - /// Do not resize. Sketch will be configured to full size. + /// Does not resize; configures the sketch at full size. X1, - /// Resize by factor of 2 + /// Resizes by a factor of `2`. X2, - /// Resize by factor of 4 + /// Resizes by a factor of `4`. X4, - /// Resize by factor of 8 + /// Resizes by a factor of `8`. X8, } impl ResizeFactor { - /// Returns the Log-base 2 of the Resize Factor + /// Returns the base-2 logarithm of the resize factor. pub fn lg_value(self) -> u8 { match self { ResizeFactor::X1 => 0, diff --git a/datasketches/src/countmin/sketch.rs b/datasketches/src/countmin/sketch.rs index 8c38284..84bbfed 100644 --- a/datasketches/src/countmin/sketch.rs +++ b/datasketches/src/countmin/sketch.rs @@ -59,7 +59,7 @@ impl CountMinSketch { /// /// # Panics /// - /// Panics if `num_hashes` is 0, `num_buckets` is less than 3, or the + /// Panics if `num_hashes` is `0`, `num_buckets` is less than `3`, or the /// total table size exceeds the supported limit. /// /// # Examples @@ -79,10 +79,10 @@ impl CountMinSketch { /// # Panics /// /// Panics if any of: - /// * `num_hashes` is 0 - /// * `num_buckets` is less than 3 - /// * the total table size exceeds the supported limit - /// * the computed seed hash is zero + /// * `num_hashes` is `0`. + /// * `num_buckets` is less than `3`. + /// * The total table size exceeds the supported limit. + /// * The computed seed hash is zero. /// /// # Examples /// @@ -122,7 +122,7 @@ impl CountMinSketch { std::f64::consts::E / self.num_buckets as f64 } - /// Returns true if the sketch has not seen any updates. + /// Returns `true` if the sketch has not seen any updates. pub fn is_empty(&self) -> bool { self.total_weight == T::ZERO } @@ -455,6 +455,10 @@ impl CountMinSketch { /// Values are truncated toward zero after multiplication; choose `decay` in `(0, 1]`. /// The total weight is scaled by the same factor to keep bounds consistent. /// + /// # Panics + /// + /// Panics if `decay` is not finite or is outside `(0, 1]`. + /// /// # Examples /// /// ``` @@ -465,10 +469,6 @@ impl CountMinSketch { /// sketch.decay(0.5); /// assert!(sketch.estimate("apple") >= 1); /// ``` - /// - /// # Panics - /// - /// Panics if `decay` is not finite or is outside `(0, 1]`. pub fn decay(&mut self, decay: f64) { assert!(decay > 0.0 && decay <= 1.0, "decay must be within (0, 1]"); for c in &mut self.counts { diff --git a/datasketches/src/cpc/sketch.rs b/datasketches/src/cpc/sketch.rs index c90b875..622b6a1 100644 --- a/datasketches/src/cpc/sketch.rs +++ b/datasketches/src/cpc/sketch.rs @@ -128,7 +128,7 @@ impl CpcSketch { } } - /// Return the parameter lg_k. + /// Returns the configured `lg_k`. pub fn lg_k(&self) -> u8 { self.lg_k } @@ -165,12 +165,12 @@ impl CpcSketch { ) } - /// Returns true if the sketch is empty. + /// Returns `true` if the sketch is empty. pub fn is_empty(&self) -> bool { self.num_coupons == 0 } - /// Update the sketch with a hashable value. + /// Updates the sketch with a hashable value. /// /// You may use [`hash::value`](crate::hash::value) wrappers when another DataSketches /// implementation requires a specific value hashing strategy. @@ -452,7 +452,7 @@ impl CpcSketch { matrix } - /// Returns the estimated size of the sketch in bytes + /// Returns the estimated size of the sketch in bytes. pub fn estimated_size(&self) -> usize { let heap_size = self.sliding_window.capacity() + self @@ -466,7 +466,7 @@ impl CpcSketch { } impl CpcSketch { - /// Serializes this CpcSketch to bytes. + /// Serializes this `CpcSketch` to bytes. pub fn serialize(&self) -> Vec { let mut bytes = SketchBytes::with_capacity(256); @@ -526,12 +526,12 @@ impl CpcSketch { bytes.into_bytes() } - /// Deserializes a CpcSketch from bytes. + /// Deserializes a `CpcSketch` from bytes. pub fn deserialize(bytes: &[u8]) -> Result { Self::deserialize_with_seed(bytes, DEFAULT_UPDATE_SEED) } - /// Deserializes a CpcSketch from bytes with the provided seed. + /// Deserializes a `CpcSketch` from bytes with the provided seed. pub fn deserialize_with_seed(bytes: &[u8], seed: u64) -> Result { let mut cursor = SketchSlice::new(bytes); let preamble_ints = cursor @@ -716,7 +716,7 @@ impl CpcSketch { // testing methods impl CpcSketch { - /// Validate this sketch is valid. + /// Returns `true` if the sketch's internal state is valid. /// /// This is primarily for testing and validation purposes. pub fn validate(&self) -> bool { diff --git a/datasketches/src/cpc/union.rs b/datasketches/src/cpc/union.rs index 5cf74d7..63198ca 100644 --- a/datasketches/src/cpc/union.rs +++ b/datasketches/src/cpc/union.rs @@ -69,7 +69,7 @@ use crate::cpc::determine_correct_offset; use crate::cpc::pair_table::PairTable; use crate::hash::DEFAULT_UPDATE_SEED; -/// The union (merge) operation for the CPC sketches. +/// Union operator for CPC sketches. #[derive(Debug, Clone)] pub struct CpcUnion { // immutable config variables @@ -108,15 +108,15 @@ impl CpcUnion { Self { lg_k, seed, state } } - /// Return the parameter lg_k. + /// Returns the current `lg_k`. /// - /// Note that due to merging with source sketches that may have a lower value of lg_k, this + /// Note that due to merging with source sketches that may have a lower `lg_k`, this /// value can be less than what the union object was configured with. pub fn lg_k(&self) -> u8 { self.lg_k } - /// Get the union result as a new sketch. + /// Returns the union result as a new sketch. /// /// # Examples /// @@ -207,7 +207,7 @@ impl CpcUnion { } } - /// Update this union with a CpcSketch. + /// Updates this union with a `CpcSketch`. /// /// # Panics /// diff --git a/datasketches/src/cpc/wrapper.rs b/datasketches/src/cpc/wrapper.rs index 51f9f9d..c0ee945 100644 --- a/datasketches/src/cpc/wrapper.rs +++ b/datasketches/src/cpc/wrapper.rs @@ -34,7 +34,7 @@ use crate::cpc::serialization::SERIAL_VERSION; use crate::cpc::serialization::make_preamble_ints; use crate::error::Error; -/// A read-only view of a serialized image of a CpcSketch. +/// A read-only view of a serialized `CpcSketch` image. #[derive(Debug, Clone)] pub struct CpcWrapper { lg_k: u8, @@ -131,7 +131,7 @@ impl CpcWrapper { }) } - /// Return the parameter lg_k. + /// Returns the configured `lg_k`. pub fn lg_k(&self) -> u8 { self.lg_k } @@ -168,7 +168,7 @@ impl CpcWrapper { ) } - /// Returns true if the sketch is empty. + /// Returns `true` if the sketch is empty. pub fn is_empty(&self) -> bool { self.num_coupons == 0 } diff --git a/datasketches/src/error.rs b/datasketches/src/error.rs index 094ab2d..3f22eff 100644 --- a/datasketches/src/error.rs +++ b/datasketches/src/error.rs @@ -15,22 +15,22 @@ // specific language governing permissions and limitations // under the License. -//! Error types for datasketches operations +//! Error types for DataSketches operations. use std::fmt; -/// ErrorKind is all kinds of Error of datasketches. +/// Categories of errors returned by DataSketches operations. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[non_exhaustive] pub enum ErrorKind { /// The argument provided is invalid. InvalidArgument, - /// The sketch data deserializing is malformed. + /// The serialized sketch data is malformed. InvalidData, } impl ErrorKind { - /// Convert this error kind instance into static str. + /// Converts this error kind into a static string. pub const fn into_static(self) -> &'static str { match self { ErrorKind::InvalidArgument => "InvalidArgument", @@ -45,7 +45,7 @@ impl fmt::Display for ErrorKind { } } -/// Error is the error struct returned by all datasketches functions. +/// Error returned by a DataSketches operation. /// /// # Examples /// @@ -64,7 +64,7 @@ pub struct Error { } impl Error { - /// Create a new Error with error kind and message. + /// Creates a new `Error` with the given kind and message. pub fn new(kind: ErrorKind, message: impl Into) -> Self { Self { kind, @@ -73,18 +73,18 @@ impl Error { } } - /// Add more context in error. + /// Adds context to the error. pub fn with_context(mut self, key: &'static str, value: impl ToString) -> Self { self.context.push((key, value.to_string())); self } - /// Return error's kind. + /// Returns the error kind. pub fn kind(&self) -> ErrorKind { self.kind } - /// Return error's message. + /// Returns the error message. pub fn message(&self) -> &str { self.message.as_str() } diff --git a/datasketches/src/frequencies/mod.rs b/datasketches/src/frequencies/mod.rs index 7dc15ec..86b5f4e 100644 --- a/datasketches/src/frequencies/mod.rs +++ b/datasketches/src/frequencies/mod.rs @@ -27,15 +27,15 @@ //! [`Hash`](std::hash::Hash), with optional associated counts (`T` item, `u64` count) that are //! members of a multiset. The true frequency of an item is the sum of its associated counts. //! -//! This implementation provides the following capabilities: -//! * Estimate the frequency of an item. -//! * Return upper and lower bounds of any item, such that the true frequency is always between the -//! upper and lower bounds. -//! * Return a global maximum error that holds for all items in the stream. -//! * Return an array of frequent items that qualify either [`ErrorType::NoFalsePositives`] or +//! This implementation: +//! * Estimates the frequency of an item. +//! * Returns upper and lower bounds for any item, such that the true frequency is always between +//! the upper and lower bounds. +//! * Returns a global maximum error that holds for all items in the stream. +//! * Returns an array of frequent items that qualify either [`ErrorType::NoFalsePositives`] or //! [`ErrorType::NoFalseNegatives`]. -//! * Merge itself with another sketch created from this module. -//! * Serialize to bytes, or deserialize from bytes, for storage or transmission. +//! * Merges itself with another sketch created from this module. +//! * Serializes to bytes and deserializes from bytes for storage or transmission. //! //! # Accuracy //! diff --git a/datasketches/src/frequencies/sketch.rs b/datasketches/src/frequencies/sketch.rs index 8c0c378..41b1ac7 100644 --- a/datasketches/src/frequencies/sketch.rs +++ b/datasketches/src/frequencies/sketch.rs @@ -47,9 +47,9 @@ const LOAD_FACTOR_DENOMINATOR: usize = 4; /// Error guarantees for frequent item queries. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ErrorType { - /// Include items if upper bound exceeds threshold (no false negatives). + /// Includes items if the upper bound exceeds the threshold (no false negatives). NoFalseNegatives, - /// Include items if lower bound exceeds threshold (no false positives). + /// Includes items if the lower bound exceeds the threshold (no false positives). NoFalsePositives, } @@ -131,7 +131,7 @@ impl FrequentItemsSketch { Self::with_lg_map_sizes(lg_max_map_size, LG_MIN_MAP_SIZE) } - /// Returns true if the sketch has no active items. + /// Returns `true` if the sketch has no active items. /// /// A purge can remove all active items while retaining a non-zero total weight and /// maximum error. Use [`Self::total_weight`] to distinguish that state from a newly created @@ -211,12 +211,12 @@ impl FrequentItemsSketch { self.offset } - /// Returns epsilon for this sketch. + /// Returns the epsilon error parameter for this sketch. pub fn epsilon(&self) -> f64 { Self::epsilon_for_lg(self.lg_max_map_size) } - /// Returns epsilon for a sketch configured with `lg_max_map_size`. + /// Returns the epsilon error parameter for the given `lg_max_map_size`. pub fn epsilon_for_lg(lg_max_map_size: u8) -> f64 { EPSILON_FACTOR / (1u64 << lg_max_map_size) as f64 } @@ -240,12 +240,12 @@ impl FrequentItemsSketch { self.cur_map_cap } - /// Returns the configured log2 maximum map size. + /// Returns the configured `lg_max_map_size`. pub fn lg_max_map_size(&self) -> u8 { self.lg_max_map_size } - /// Returns the current map size in log2. + /// Returns the current `lg_cur_map_size`. pub fn lg_cur_map_size(&self) -> u8 { self.hash_map.lg_length() } diff --git a/datasketches/src/hash/value/canonical_float.rs b/datasketches/src/hash/value/canonical_float.rs index 6ed9387..0feb526 100644 --- a/datasketches/src/hash/value/canonical_float.rs +++ b/datasketches/src/hash/value/canonical_float.rs @@ -38,7 +38,7 @@ pub type CanonicalFloat = Value; #[doc(hidden)] pub struct CanonicalFloatStrategy; -/// Create a canonical hashable value from a `f32` value. +/// Creates a canonical hashable value from an `f32` value. /// /// `f32` values are converted to `f64` before hashing. Values that are not exactly representable /// in `f32` may hash differently from the corresponding `f64` value. Signed zero values hash the @@ -68,7 +68,7 @@ pub fn from_f32(v: f32) -> CanonicalFloat { CanonicalFloat::new(v) } -/// Create a canonical hashable value from a `f64` value. +/// Creates a canonical hashable value from an `f64` value. /// /// Signed zero values hash the same, and all NaN values use one canonical NaN bit pattern. /// diff --git a/datasketches/src/hash/value/mod.rs b/datasketches/src/hash/value/mod.rs index 2455965..ee42e19 100644 --- a/datasketches/src/hash/value/mod.rs +++ b/datasketches/src/hash/value/mod.rs @@ -29,7 +29,7 @@ //! //! This strategy is the same as how other datasketches implementations hash floating-point numbers. //! -//! Read the docs of concrete value wrapper for more details and examples. +//! The concrete wrapper documentation provides more details and examples. //! //! * [`canonical_float::from_f32`] //! * [`canonical_float::from_f64`] @@ -40,7 +40,7 @@ //! integers. This strategy is the same as how datasketches-cpp hashes short integers for //! `HllSketch` and `CpcSketch`. //! -//! Read the docs of concrete value wrapper for more details and examples. +//! The concrete wrapper documentation provides more details and examples. //! //! * [`sign_extend::from_i8`], [`sign_extend::from_u8`] //! * [`sign_extend::from_i16`], [`sign_extend::from_u16`] @@ -50,7 +50,7 @@ //! `u64`, and then hashes the resulting integers. This strategy is the same as how datasketches-cpp //! hashes short integers for `BloomFilter`. //! -//! Read the docs of concrete value wrapper for more details and examples. +//! The concrete wrapper documentation provides more details and examples. //! //! * [`natural_extend::from_i8`], [`natural_extend::from_u8`] //! * [`natural_extend::from_i16`], [`natural_extend::from_u16`] @@ -65,7 +65,7 @@ //! empty strings before hashing, so check `is_empty` before updating a sketch when that behavior //! matters. //! -//! Read the docs of concrete value wrapper for more details and examples. +//! The concrete wrapper documentation provides more details and examples. //! //! * [`raw_bytes::from_vec`] //! * [`raw_bytes::from_string`] diff --git a/datasketches/src/hash/value/natural_extend.rs b/datasketches/src/hash/value/natural_extend.rs index 375fcad..919060e 100644 --- a/datasketches/src/hash/value/natural_extend.rs +++ b/datasketches/src/hash/value/natural_extend.rs @@ -37,7 +37,7 @@ pub type NaturalExtend = Value; #[doc(hidden)] pub struct NaturalExtendStrategy; -/// Create a naturally extended hashable value from an `i8` value. +/// Creates a naturally extended hashable value from an `i8` value. /// /// # Examples /// @@ -52,7 +52,7 @@ pub fn from_i8(v: i8) -> NaturalExtend { NaturalExtend::new(v) } -/// Create a naturally extended hashable value from a `u8` value. +/// Creates a naturally extended hashable value from a `u8` value. /// /// # Examples /// @@ -67,7 +67,7 @@ pub fn from_u8(v: u8) -> NaturalExtend { NaturalExtend::new(v) } -/// Create a naturally extended hashable value from an `i16` value. +/// Creates a naturally extended hashable value from an `i16` value. /// /// # Examples /// @@ -82,7 +82,7 @@ pub fn from_i16(v: i16) -> NaturalExtend { NaturalExtend::new(v) } -/// Create a naturally extended hashable value from a `u16` value. +/// Creates a naturally extended hashable value from a `u16` value. /// /// # Examples /// @@ -97,7 +97,7 @@ pub fn from_u16(v: u16) -> NaturalExtend { NaturalExtend::new(v) } -/// Create a naturally extended hashable value from an `i32` value. +/// Creates a naturally extended hashable value from an `i32` value. /// /// # Examples /// @@ -112,7 +112,7 @@ pub fn from_i32(v: i32) -> NaturalExtend { NaturalExtend::new(v) } -/// Create a naturally extended hashable value from a `u32` value. +/// Creates a naturally extended hashable value from a `u32` value. /// /// # Examples /// diff --git a/datasketches/src/hash/value/raw_bytes.rs b/datasketches/src/hash/value/raw_bytes.rs index 1847711..55e79ad 100644 --- a/datasketches/src/hash/value/raw_bytes.rs +++ b/datasketches/src/hash/value/raw_bytes.rs @@ -38,7 +38,7 @@ pub type RawBytes = Value; #[doc(hidden)] pub struct RawBytesStrategy; -/// Create a raw-byte hashable value from a byte vector. +/// Creates a raw-byte hashable value from a byte vector. /// /// This hashes the vector contents without Rust's slice length prefix. /// @@ -60,7 +60,7 @@ pub fn from_vec(v: Vec) -> RawBytes> { RawBytes::new(v) } -/// Create a raw-byte hashable value from a string. +/// Creates a raw-byte hashable value from a string. /// /// This hashes the UTF-8 bytes of the string without Rust's string length prefix. /// @@ -82,7 +82,7 @@ pub fn from_string(v: String) -> RawBytes { RawBytes::new(v) } -/// Create a raw-byte hashable value from a byte slice. +/// Creates a raw-byte hashable value from a byte slice. /// /// This hashes the slice contents without Rust's slice length prefix. /// @@ -104,7 +104,7 @@ pub fn from_slice(v: &[u8]) -> RawBytes<&[u8]> { RawBytes::new(v) } -/// Create a raw-byte hashable value from a string slice. +/// Creates a raw-byte hashable value from a string slice. /// /// This hashes the UTF-8 bytes of the string slice without Rust's string length prefix. /// diff --git a/datasketches/src/hash/value/sign_extend.rs b/datasketches/src/hash/value/sign_extend.rs index 0672f93..060072b 100644 --- a/datasketches/src/hash/value/sign_extend.rs +++ b/datasketches/src/hash/value/sign_extend.rs @@ -37,7 +37,7 @@ pub type SignExtend = Value; #[doc(hidden)] pub struct SignExtendStrategy; -/// Create a sign-extended hashable value from an `i8` value. +/// Creates a sign-extended hashable value from an `i8` value. /// /// # Examples /// @@ -54,7 +54,7 @@ pub fn from_i8(v: i8) -> SignExtend { SignExtend::new(v) } -/// Create a sign-extended hashable value from a `u8` value. +/// Creates a sign-extended hashable value from a `u8` value. /// /// `255u8` sign-extends like `-1i8`, not like `255u64`. /// @@ -73,7 +73,7 @@ pub fn from_u8(v: u8) -> SignExtend { SignExtend::new(v) } -/// Create a sign-extended hashable value from an `i16` value. +/// Creates a sign-extended hashable value from an `i16` value. /// /// # Examples /// @@ -93,7 +93,7 @@ pub fn from_i16(v: i16) -> SignExtend { SignExtend::new(v) } -/// Create a sign-extended hashable value from a `u16` value. +/// Creates a sign-extended hashable value from a `u16` value. /// /// `65535u16` sign-extends like `-1i16`, not like `65535u64`. /// @@ -115,7 +115,7 @@ pub fn from_u16(v: u16) -> SignExtend { SignExtend::new(v) } -/// Create a sign-extended hashable value from an `i32` value. +/// Creates a sign-extended hashable value from an `i32` value. /// /// # Examples /// @@ -135,7 +135,7 @@ pub fn from_i32(v: i32) -> SignExtend { SignExtend::new(v) } -/// Create a sign-extended hashable value from a `u32` value. +/// Creates a sign-extended hashable value from a `u32` value. /// /// `4294967295u32` sign-extends like `-1i32`, not like `4294967295u64`. /// diff --git a/datasketches/src/hll/mod.rs b/datasketches/src/hll/mod.rs index 90d0465..8f0ece6 100644 --- a/datasketches/src/hll/mod.rs +++ b/datasketches/src/hll/mod.rs @@ -136,19 +136,15 @@ pub use self::union::HllUnion; /// See [module level documentation](self) for more details. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum HllType { - /// Uses a 4-bit field per HLL bucket and for large counts may require the use of a - /// small internal auxiliary array for storing statistical exceptions, which are rare. - /// For the values of lgConfigK > 13 (K = 8192), this additional array adds about 3% - /// to the overall storage. + /// Uses 4 bits per HLL bucket and has the smallest storage footprint. /// - /// It is generally the slowest in terms of update time, but has the smallest storage - /// footprint of about K/2 * 1.03 bytes. + /// It is generally the slowest representation to update. Hll4, - /// Uses a 6-bit field per HLL bucket. It is generally the next fastest in terms - /// of update time with a storage footprint of about 3/4 * K bytes. + /// Uses 6 bits per HLL bucket and provides a middle ground for storage and update speed. Hll6, - /// Uses an 8-bit byte per HLL bucket. It is generally the fastest in terms of update - /// time but has the largest storage footprint of about K bytes. + /// Uses 8 bits per HLL bucket and has the largest storage footprint. + /// + /// It is generally the fastest representation to update. Hll8, } @@ -211,7 +207,7 @@ impl Coupon { self.0 } - /// Compute the HLL coupon for a hashable value. + /// Computes the HLL coupon for a hashable value. /// /// You may use [`hash::value`](crate::hash::value) wrappers when another DataSketches /// implementation requires a specific value hashing strategy. diff --git a/datasketches/src/hll/sketch.rs b/datasketches/src/hll/sketch.rs index 9efd6ff..21f5d53 100644 --- a/datasketches/src/hll/sketch.rs +++ b/datasketches/src/hll/sketch.rs @@ -65,19 +65,19 @@ pub struct HllSketch { } impl HllSketch { - /// Create a new HLL sketch + /// Creates a new HLL sketch. /// /// # Arguments /// - /// * `lg_config_k`: Log2 of the number of buckets (K). Must be in `[4, 21]`. - /// * lg_k=4: 16 buckets, ~26% relative error - /// * lg_k=12: 4096 buckets, ~1.6% relative error (common choice) - /// * lg_k=21: 2M buckets, ~0.4% relative error - /// * `hll_type`: Target HLL array type (Hll4, Hll6, or Hll8) + /// * `lg_config_k`: The `lg_k` value in `[4, 21]`, which controls the number of buckets. + /// * `lg_k = 4`: 16 buckets, ~26% relative error. + /// * `lg_k = 12`: 4096 buckets, ~1.6% relative error (common choice). + /// * `lg_k = 21`: 2M buckets, ~0.4% relative error. + /// * `hll_type`: Target HLL array type (`Hll4`, `Hll6`, or `Hll8`). /// /// # Panics /// - /// If lg_config_k is not in range `[4, 21]` + /// Panics if `lg_config_k` is outside `[4, 21]`. /// /// # Examples /// @@ -130,7 +130,7 @@ impl HllSketch { &mut self.mode } - /// Check if the sketch is empty (no values have been added) + /// Returns `true` if no values have been added to the sketch. pub fn is_empty(&self) -> bool { match &self.mode { Mode::List { list, .. } => list.container().is_empty(), @@ -141,7 +141,7 @@ impl HllSketch { } } - /// Get the target HLL type for this sketch + /// Returns the target HLL type for this sketch. pub fn target_type(&self) -> HllType { match &self.mode { Mode::List { hll_type, .. } => *hll_type, @@ -152,12 +152,12 @@ impl HllSketch { } } - /// Get the configured lg_config_k + /// Returns the configured `lg_k`. pub fn lg_config_k(&self) -> u8 { self.lg_config_k } - /// Update the sketch with a value. + /// Updates the sketch with a value. /// /// Accepts any type that implements [`Hash`]. The value is hashed and converted to /// an internal coupon, which is then inserted into the sketch. @@ -189,15 +189,15 @@ impl HllSketch { self.update_with_coupon(Coupon::from_value(value)); } - /// Update the sketch with a pre-computed [`Coupon`]. + /// Updates the sketch with a pre-computed [`Coupon`]. /// /// A [`Coupon`] encodes both the HLL bucket index (low 26 bits) and the register /// value (high 6 bits) derived from hashing an input. Accepting a pre-computed /// coupon makes it possible to pay the hashing cost once and fan the result out to /// many independent sketches — see [`Coupon`] for a worked example. /// - /// Handles all internal bookkeeping, including automatic mode transitions - /// (List → Set → HLL array) and estimator state updates. + /// All internal bookkeeping, including representation transitions and estimator state updates, + /// is handled automatically. /// /// # Examples /// @@ -242,7 +242,7 @@ impl HllSketch { } } - /// Get the current cardinality estimate + /// Returns the current cardinality estimate. /// /// # Examples /// @@ -264,10 +264,9 @@ impl HllSketch { } } - /// Get upper bound for cardinality estimate + /// Returns the upper confidence bound for the cardinality estimate. /// - /// Returns the upper confidence bound for the cardinality estimate based on - /// the number of standard deviations requested. + /// The bound is based on the requested number of standard deviations. pub fn upper_bound(&self, num_std_dev: NumStdDev) -> f64 { match &self.mode { Mode::List { list, .. } => list.container().upper_bound(num_std_dev), @@ -278,10 +277,9 @@ impl HllSketch { } } - /// Get lower bound for cardinality estimate + /// Returns the lower confidence bound for the cardinality estimate. /// - /// Returns the lower confidence bound for the cardinality estimate based on - /// the number of standard deviations requested. + /// The bound is based on the requested number of standard deviations. pub fn lower_bound(&self, num_std_dev: NumStdDev) -> f64 { match &self.mode { Mode::List { list, .. } => list.container().lower_bound(num_std_dev), @@ -292,7 +290,7 @@ impl HllSketch { } } - /// Deserializes an HLL sketch from bytes + /// Deserializes an HLL sketch from bytes. /// /// # Examples /// @@ -409,7 +407,7 @@ impl HllSketch { Ok(HllSketch { lg_config_k, mode }) } - /// Serializes the HLL sketch to bytes + /// Serializes the HLL sketch to bytes. /// /// # Examples /// @@ -434,7 +432,7 @@ impl HllSketch { } } - /// Returns the estimated size of the sketch in bytes + /// Returns the estimated size of the sketch in bytes. pub fn estimated_size(&self) -> usize { let heap_size = match &self.mode { Mode::List { list, .. } => list.container().estimated_size(), diff --git a/datasketches/src/hll/union.rs b/datasketches/src/hll/union.rs index a710fd9..df86272 100644 --- a/datasketches/src/hll/union.rs +++ b/datasketches/src/hll/union.rs @@ -39,7 +39,7 @@ use crate::hll::array6::Array6; use crate::hll::array8::Array8; use crate::hll::mode::Mode; -/// An HLL Union for combining multiple HLL sketches. +/// An HLL union for combining multiple HLL sketches. /// /// The union accumulates the distinct values represented by all input sketches and automatically /// handles sketches with different configurations. @@ -59,17 +59,16 @@ pub struct HllUnion { } impl HllUnion { - /// Create a new HLL Union + /// Creates a new HLL union. /// /// # Arguments /// - /// * `lg_max_k`: Maximum log2 of the number of buckets. Must be in `[4, 21]`. This determines - /// the maximum precision the union can handle. Input sketches with larger lg_k will be - /// down-sampled. + /// * `lg_max_k`: Maximum `lg_k` in `[4, 21]`. This determines the maximum precision the union + /// can handle. Input sketches with a larger `lg_k` are downsampled. /// /// # Panics /// - /// Panics if `lg_max_k` is not in the range `[4, 21]`. + /// Panics if `lg_max_k` is outside `[4, 21]`. /// /// # Examples /// @@ -95,7 +94,7 @@ impl HllUnion { Self { lg_max_k, gadget } } - /// Update the union's gadget with a value + /// Updates the union with a hashable value. /// /// This accepts any type that implements `Hash`. The value is hashed /// and converted to a coupon, which is then inserted into the sketch. @@ -115,12 +114,10 @@ impl HllUnion { self.gadget.update(value); } - /// Update the union with another sketch + /// Updates the union with another sketch. /// - /// Merges the input sketch into the union's internal gadget, handling: - /// * Sketches with different `lg_k` values (resizes/downsamples as needed) - /// * Sketches in different modes (List, Set, Array4/6/8) - /// * Sketches with different target HLL types + /// The input is merged while accommodating different `lg_k` configurations and target HLL + /// types. The union's effective `lg_k` may decrease as a result. /// /// # Examples /// @@ -246,14 +243,14 @@ impl HllUnion { self.gadget = HllSketch::from_mode(final_lg_k, Mode::Array8(new_array)); } - /// Get the union result as a new sketch. + /// Returns the union result as a new sketch. /// - /// Returns a copy of the internal gadget sketch with the specified target HLL type. - /// If the requested type differs from the gadget's type, conversion is performed. + /// The returned sketch uses the specified target HLL type. If the requested type differs from + /// the current representation, the result is converted. /// /// # Arguments /// - /// * `hll_type`: The target HLL type for the result sketch (Hll4, Hll6, or Hll8) + /// * `hll_type`: Target HLL type for the result sketch (`Hll4`, `Hll6`, or `Hll8`). /// /// # Examples /// @@ -297,46 +294,43 @@ impl HllUnion { } } - /// Get the current lg_config_k of the internal gadget + /// Returns the union's current effective `lg_k`. pub fn lg_config_k(&self) -> u8 { self.gadget.lg_config_k() } - /// Get the maximum lg_k this union can handle + /// Returns the maximum configured `lg_k`. pub fn lg_max_k(&self) -> u8 { self.lg_max_k } - /// Check if the union is empty + /// Returns `true` if the union is empty. pub fn is_empty(&self) -> bool { self.gadget.is_empty() } - /// Reset the union to its initial empty state + /// Resets the union to its initial empty state. /// - /// Clears all data from the internal gadget, allowing the union to be reused - /// for a new set of operations. + /// This clears all accumulated data so the union can be reused. pub fn reset(&mut self) { self.gadget = HllSketch::new(self.lg_max_k, HllType::Hll8); } - /// Get the current cardinality estimate of the union + /// Returns the union's current cardinality estimate. pub fn estimate(&self) -> f64 { self.gadget.estimate() } - /// Get upper bound for cardinality estimate of the union + /// Returns the upper confidence bound for the union's cardinality estimate. /// - /// Returns the upper confidence bound for the cardinality estimate based on - /// the number of standard deviations requested. + /// The bound is based on the requested number of standard deviations. pub fn upper_bound(&self, num_std_dev: NumStdDev) -> f64 { self.gadget.upper_bound(num_std_dev) } - /// Get lower bound for cardinality estimate of the union + /// Returns the lower confidence bound for the union's cardinality estimate. /// - /// Returns the lower confidence bound for the cardinality estimate based on - /// the number of standard deviations requested. + /// The bound is based on the requested number of standard deviations. pub fn lower_bound(&self, num_std_dev: NumStdDev) -> f64 { self.gadget.lower_bound(num_std_dev) } diff --git a/datasketches/src/tdigest/mod.rs b/datasketches/src/tdigest/mod.rs index 5590c75..1f67087 100644 --- a/datasketches/src/tdigest/mod.rs +++ b/datasketches/src/tdigest/mod.rs @@ -23,9 +23,9 @@ //! The implementation in this library has a few differences from the reference implementation //! associated with that paper: //! -//! * Merge does not modify the input -//! * Deserialization similar to other sketches in this library, although reading the reference -//! implementation format is supported +//! * Merging does not modify the input. +//! * Deserialization is similar to other sketches in this library, although reading the reference +//! implementation format is supported. //! //! Unlike all other algorithms in the library, t-digest is empirical and has no mathematical //! basis for estimating its error and its results are dependent on the input data. However, diff --git a/datasketches/src/tdigest/sketch.rs b/datasketches/src/tdigest/sketch.rs index 3f26b00..8ae557f 100644 --- a/datasketches/src/tdigest/sketch.rs +++ b/datasketches/src/tdigest/sketch.rs @@ -66,13 +66,13 @@ impl Default for TDigestMut { } impl TDigestMut { - /// Creates a tdigest instance with the given value of k. + /// Creates a mutable t-digest with the given `k` value. /// /// The fallible version of this method is [`TDigestMut::try_new`]. /// /// # Panics /// - /// Panics if k is less than 10 + /// Panics if `k` is less than `10`. /// /// # Examples /// @@ -94,13 +94,13 @@ impl TDigestMut { ) } - /// Creates a tdigest instance with the given value of k. + /// Creates a mutable t-digest with the given `k` value. /// /// The panicking version of this method is [`TDigestMut::new`]. /// /// # Errors /// - /// If k is less than 10. + /// Returns an error if `k` is less than `10`. /// /// # Examples /// @@ -158,7 +158,7 @@ impl TDigestMut { } } - /// Update this TDigest with the given value. + /// Updates this t-digest with the given value. /// /// [f64::NAN], [f64::INFINITY], and [f64::NEG_INFINITY] values are ignored. /// @@ -185,17 +185,17 @@ impl TDigestMut { self.max = self.max.max(value); } - /// Returns parameter k (compression) that was used to configure this TDigest. + /// Returns the compression parameter `k` used to configure this t-digest. pub fn k(&self) -> u16 { self.k } - /// Returns true if TDigest has not seen any data. + /// Returns `true` if this t-digest has not seen any data. pub fn is_empty(&self) -> bool { self.centroids.is_empty() && self.buffer.is_empty() } - /// Returns minimum value seen by TDigest; `None` if TDigest is empty. + /// Returns the minimum value seen by this t-digest, or `None` if it is empty. pub fn min_value(&self) -> Option { if self.is_empty() { None @@ -204,7 +204,7 @@ impl TDigestMut { } } - /// Returns maximum value seen by TDigest; `None` if TDigest is empty. + /// Returns the maximum value seen by this t-digest, or `None` if it is empty. pub fn max_value(&self) -> Option { if self.is_empty() { None @@ -213,12 +213,12 @@ impl TDigestMut { } } - /// Returns total weight. + /// Returns the total weight. pub fn total_weight(&self) -> u64 { self.centroids_weight + self.buffer.len() as u64 } - /// Merge the given TDigest into this one + /// Merges the given t-digest into this one. /// /// # Examples /// @@ -258,7 +258,7 @@ impl TDigestMut { self.do_merge(tmp, self.buffer.len() as u64 + other.total_weight()) } - /// Freezes this TDigest into an immutable one. + /// Converts this mutable t-digest into an immutable one. /// /// # Examples /// @@ -292,7 +292,7 @@ impl TDigestMut { } } - /// See [`TDigest::cdf`]. + /// Returns the cumulative distribution approximation described by [`TDigest::cdf`]. /// /// # Examples /// @@ -316,7 +316,7 @@ impl TDigestMut { self.view().cdf(split_points) } - /// See [`TDigest::pmf`]. + /// Returns the probability mass approximation described by [`TDigest::pmf`]. /// /// # Examples /// @@ -340,7 +340,7 @@ impl TDigestMut { self.view().pmf(split_points) } - /// See [`TDigest::rank`]. + /// Returns the normalized rank described by [`TDigest::rank`]. /// /// # Examples /// @@ -374,7 +374,7 @@ impl TDigestMut { self.view().rank(value) } - /// See [`TDigest::quantile`]. + /// Returns the quantile described by [`TDigest::quantile`]. /// /// # Examples /// @@ -398,7 +398,7 @@ impl TDigestMut { self.view().quantile(rank) } - /// Serializes this TDigest to bytes. + /// Serializes this mutable t-digest to bytes. /// /// # Examples /// @@ -483,7 +483,7 @@ impl TDigestMut { bytes.into_bytes() } - /// Deserializes a TDigest from bytes. + /// Deserializes a mutable t-digest from bytes. /// /// Supports reading compact format with (float, int) centroids as opposed to (double, long) to /// represent (mean, weight). [^1] @@ -814,7 +814,7 @@ impl TDigestMut { self.buffer.clear(); } - /// Returns the estimated size of the sketch in bytes + /// Returns the estimated size of the sketch in bytes. pub fn estimated_size(&self) -> usize { size_of::() + self.centroids.capacity() * size_of::() @@ -837,17 +837,17 @@ pub struct TDigest { } impl TDigest { - /// Returns parameter k (compression) that was used to configure this TDigest. + /// Returns the compression parameter `k` used to configure this t-digest. pub fn k(&self) -> u16 { self.k } - /// Returns true if TDigest has not seen any data. + /// Returns `true` if this t-digest has not seen any data. pub fn is_empty(&self) -> bool { self.centroids.is_empty() } - /// Returns minimum value seen by TDigest; `None` if TDigest is empty. + /// Returns the minimum value seen by this t-digest, or `None` if it is empty. pub fn min_value(&self) -> Option { if self.is_empty() { None @@ -856,7 +856,7 @@ impl TDigest { } } - /// Returns maximum value seen by TDigest; `None` if TDigest is empty. + /// Returns the maximum value seen by this t-digest, or `None` if it is empty. pub fn max_value(&self) -> Option { if self.is_empty() { None @@ -865,7 +865,7 @@ impl TDigest { } } - /// Returns total weight. + /// Returns the total weight. pub fn total_weight(&self) -> u64 { self.centroids_weight } @@ -895,7 +895,7 @@ impl TDigest { /// This can be viewed as array of ranks of the given split points plus one more value that /// is always 1. /// - /// Returns `None` if TDigest is empty. + /// Returns `None` if this t-digest is empty. /// /// # Panics /// @@ -932,7 +932,7 @@ impl TDigest { /// An array of m+1 doubles each of which is an approximation to the fraction of the input /// stream values (the mass) that fall into one of those intervals. /// - /// Returns `None` if TDigest is empty. + /// Returns `None` if this t-digest is empty. /// /// # Panics /// @@ -956,9 +956,9 @@ impl TDigest { self.view().pmf(split_points) } - /// Compute approximate normalized rank (from 0 to 1 inclusive) of the given value. + /// Computes the approximate normalized rank in `[0.0, 1.0]` of the given value. /// - /// Returns `None` if TDigest is empty. + /// Returns `None` if this t-digest is empty. /// /// # Panics /// @@ -982,13 +982,13 @@ impl TDigest { self.view().rank(value) } - /// Compute approximate quantile value corresponding to the given normalized rank. + /// Computes the approximate quantile for the given normalized rank. /// - /// Returns `None` if TDigest is empty. + /// Returns `None` if this t-digest is empty. /// /// # Panics /// - /// Panics if rank is not in [0.0, 1.0]. + /// Panics if `rank` is outside `[0.0, 1.0]`. /// /// # Examples /// @@ -1008,7 +1008,7 @@ impl TDigest { self.view().quantile(rank) } - /// Converts this immutable TDigest into a mutable one. + /// Converts this immutable t-digest into a mutable one. /// /// # Examples /// @@ -1034,7 +1034,7 @@ impl TDigest { ) } - /// Returns the estimated size of the sketch in bytes + /// Returns the estimated size of the sketch in bytes. pub fn estimated_size(&self) -> usize { size_of::() + self.centroids.capacity() * size_of::() } diff --git a/datasketches/src/thetafamily/theta/a_not_b.rs b/datasketches/src/thetafamily/theta/a_not_b.rs index 29ea2f8..d8edbd1 100644 --- a/datasketches/src/thetafamily/theta/a_not_b.rs +++ b/datasketches/src/thetafamily/theta/a_not_b.rs @@ -72,7 +72,7 @@ impl ThetaANotB { /// Computes `a and not b`. /// /// The result retains every key of `a` (below the combined theta) that is not present in `b`. - /// If `ordered` is true, the retained entries are sorted ascending by hash. + /// If `ordered` is `true`, the retained entries are sorted ascending by hash. /// /// # Errors /// diff --git a/datasketches/src/thetafamily/theta/hash_table.rs b/datasketches/src/thetafamily/theta/hash_table.rs index d7dd23b..6cd1735 100644 --- a/datasketches/src/thetafamily/theta/hash_table.rs +++ b/datasketches/src/thetafamily/theta/hash_table.rs @@ -42,7 +42,7 @@ impl ThetaEntry { Self { hash } } - /// Return the hash used as this entry's key. + /// Returns the hash used as this entry's key. pub fn hash(&self) -> u64 { self.hash.get() } @@ -57,7 +57,7 @@ impl SketchEntry for ThetaEntry { impl ThetaHashTable { /// Hashes and inserts a value into the table. /// - /// Returns true if the value was inserted (new), false otherwise. + /// Returns `true` if the value was inserted, or `false` otherwise. pub fn try_insert(&mut self, value: T) -> bool { let hash = self.hash(value); self.try_insert_hash(hash) @@ -65,7 +65,7 @@ impl ThetaHashTable { /// Inserts a pre-hashed value into the table. /// - /// Returns true if the value was inserted (new), false otherwise. + /// Returns `true` if the value was inserted, or `false` otherwise. pub fn try_insert_hash(&mut self, hash: u64) -> bool { self.upsert_entry(hash, |existing| { if existing.is_some() { diff --git a/datasketches/src/thetafamily/theta/mod.rs b/datasketches/src/thetafamily/theta/mod.rs index e63fffe..6a70a6b 100644 --- a/datasketches/src/thetafamily/theta/mod.rs +++ b/datasketches/src/thetafamily/theta/mod.rs @@ -20,15 +20,15 @@ //! Theta sketch is a generalization of the Kth Minimum Value (KMV) sketch that uses //! a hash table to store retained entries and a theta parameter (sampling threshold) //! to control memory usage. When the hash table reaches capacity, theta is reduced -//! to maintain the nominal size k. +//! to maintain the capacity configured by `lg_k`. //! //! # Overview //! //! Theta sketches provide approximate distinct count (cardinality) estimation with //! configurable accuracy and memory usage. The implementation supports: //! -//! * **ThetaSketch**: Mutable sketch for building from input data -//! * **CompactThetaSketch**: Immutable sketch with compact memory layout +//! * [`ThetaSketch`]: Mutable sketch for building from input data. +//! * [`CompactThetaSketch`]: Immutable sketch with a compact memory layout. //! //! # Usage //! diff --git a/datasketches/src/thetafamily/theta/sketch.rs b/datasketches/src/thetafamily/theta/sketch.rs index 2c3bf56..ed91d97 100644 --- a/datasketches/src/thetafamily/theta/sketch.rs +++ b/datasketches/src/thetafamily/theta/sketch.rs @@ -198,7 +198,7 @@ impl<'a> From<&'a CompactThetaSketch> for ThetaSketchView<'a> { } } -/// Mutable theta sketch for building from input data +/// Mutable theta sketch for building from input data. #[derive(Debug)] pub struct ThetaSketch { table: ThetaHashTable, @@ -210,7 +210,7 @@ impl ThetaSketch { self.into() } - /// Update the sketch with a hashable value. + /// Updates the sketch with a hashable value. /// /// You may use [`hash::value`](crate::hash::value) wrappers when another DataSketches /// implementation requires a specific value hashing strategy. @@ -233,7 +233,7 @@ impl ThetaSketch { self.table.try_insert(value); } - /// Return cardinality estimate + /// Returns the cardinality estimate. /// /// # Examples /// @@ -253,52 +253,52 @@ impl ThetaSketch { num_retained / theta } - /// Return theta as a fraction (0.0 to 1.0) + /// Returns theta as a fraction in `[0.0, 1.0]`. pub fn theta(&self) -> f64 { self.table.theta() as f64 / MAX_THETA as f64 } - /// Return theta as u64 + /// Returns theta as a `u64`. pub fn theta64(&self) -> u64 { self.table.theta() } - /// Return 16-bit seed hash. + /// Returns the 16-bit seed hash. pub fn seed_hash(&self) -> u16 { self.table.seed_hash() } - /// Check if sketch is empty + /// Returns `true` if the sketch is empty. pub fn is_empty(&self) -> bool { self.table.is_empty() } - /// Check if sketch is in estimation mode + /// Returns `true` if the sketch is in estimation mode. pub fn is_estimation_mode(&self) -> bool { self.table.theta() < MAX_THETA } - /// Return number of retained entries + /// Returns the number of retained entries. pub fn num_retained(&self) -> usize { self.table.num_retained() } - /// Return lg_k + /// Returns the configured `lg_k`. pub fn lg_k(&self) -> u8 { self.table.lg_nom_size() } - /// Trim the sketch to nominal size k + /// Trims the sketch to the capacity configured by `lg_k`. pub fn trim(&mut self) { self.table.trim(); } - /// Reset the sketch to empty state + /// Resets the sketch to its empty state. pub fn reset(&mut self) { self.table.reset(); } - /// Return iterator over retained entries. + /// Returns an iterator over retained entries. /// /// # Examples /// @@ -314,9 +314,9 @@ impl ThetaSketch { self.table.iter_entries().copied() } - /// Return this sketch in compact (immutable) form. + /// Returns this sketch in compact, immutable form. /// - /// If `ordered` is true, retained hash values are sorted in ascending order. + /// If `ordered` is `true`, retained hash values are sorted in ascending order. /// /// # Examples /// @@ -343,7 +343,7 @@ impl ThetaSketch { ) } - /// Returns the approximate lower error bound given the specified number of Standard Deviations. + /// Returns the approximate lower error bound for the specified number of standard deviations. /// /// # Arguments /// @@ -377,7 +377,7 @@ impl ThetaSketch { .expect("theta should always be valid") } - /// Returns the approximate upper error bound given the specified number of Standard Deviations. + /// Returns the approximate upper error bound for the specified number of standard deviations. /// /// # Arguments /// @@ -416,7 +416,7 @@ impl ThetaSketch { .expect("theta should always be valid") } - /// Returns the estimated size of the sketch in bytes + /// Returns the estimated size of the sketch in bytes. pub fn estimated_size(&self) -> usize { size_of::() + self.table.estimated_size() } @@ -470,22 +470,22 @@ impl CompactThetaSketch { num_retained / theta } - /// Returns theta as a fraction (0.0 to 1.0). + /// Returns theta as a fraction in `[0.0, 1.0]`. pub fn theta(&self) -> f64 { self.theta as f64 / MAX_THETA as f64 } - /// Returns theta as u64. + /// Returns theta as a `u64`. pub fn theta64(&self) -> u64 { self.theta } - /// Returns true if this sketch is empty. + /// Returns `true` if this sketch is empty. pub fn is_empty(&self) -> bool { self.empty } - /// Returns true if this sketch is in estimation mode. + /// Returns `true` if this sketch is in estimation mode. pub fn is_estimation_mode(&self) -> bool { self.theta < MAX_THETA } @@ -495,7 +495,7 @@ impl CompactThetaSketch { self.entries.len() } - /// Returns true if retained entries are ordered (sorted ascending). + /// Returns `true` if retained entries are ordered (sorted ascending). pub fn is_ordered(&self) -> bool { self.ordered } @@ -505,12 +505,12 @@ impl CompactThetaSketch { self.seed_hash } - /// Return iterator over retained entries. + /// Returns an iterator over retained entries. pub fn iter(&self) -> impl Iterator + '_ { self.entries.iter().copied().map(ThetaEntry::new) } - /// Returns the approximate lower error bound given the specified number of Standard Deviations. + /// Returns the approximate lower error bound for the specified number of standard deviations. pub fn lower_bound(&self, num_std_dev: NumStdDev) -> f64 { if !self.is_estimation_mode() { return self.num_retained() as f64; @@ -519,7 +519,7 @@ impl CompactThetaSketch { .expect("compact theta should always be valid") } - /// Returns the approximate upper error bound given the specified number of Standard Deviations. + /// Returns the approximate upper error bound for the specified number of standard deviations. pub fn upper_bound(&self, num_std_dev: NumStdDev) -> f64 { if !self.is_estimation_mode() { return self.num_retained() as f64; @@ -979,13 +979,13 @@ impl CompactThetaSketch { }) } - /// Returns the estimated size of the sketch in bytes + /// Returns the estimated size of the sketch in bytes. pub fn estimated_size(&self) -> usize { size_of::() + self.entries.capacity() * size_of::() } } -/// Builder for ThetaSketch +/// Builder for [`ThetaSketch`]. #[derive(Debug)] pub struct ThetaSketchBuilder { lg_k: u8, @@ -1006,11 +1006,11 @@ impl Default for ThetaSketchBuilder { } impl ThetaSketchBuilder { - /// Set lg_k (log2 of nominal size k). + /// Sets `lg_k`, the base-2 logarithm of the nominal capacity. /// /// # Panics /// - /// If lg_k is not in range [5, 26] + /// Panics if `lg_k` is outside `[5, 26]`. /// /// # Examples /// @@ -1032,20 +1032,20 @@ impl ThetaSketchBuilder { self } - /// Set resize factor. + /// Sets the resize factor. pub fn resize_factor(mut self, factor: ResizeFactor) -> Self { self.resize_factor = factor; self } - /// Set sampling probability p. + /// Sets the sampling probability. /// /// The sampling probability controls the fraction of hashed values that are retained. - /// Must be greater than 0 to ensure valid theta values for bound calculations. + /// It must be greater than `0.0` to ensure valid theta values for bound calculations. /// /// # Panics /// - /// Panics if p is not in range `(0.0, 1.0]` + /// Panics if `probability` is outside `(0.0, 1.0]`. /// /// # Examples /// @@ -1065,7 +1065,7 @@ impl ThetaSketchBuilder { self } - /// Set hash seed. + /// Sets the hash seed. /// /// # Examples /// @@ -1079,7 +1079,7 @@ impl ThetaSketchBuilder { self } - /// Build the ThetaSketch. + /// Builds the [`ThetaSketch`]. /// /// # Examples /// diff --git a/datasketches/src/thetafamily/theta/union.rs b/datasketches/src/thetafamily/theta/union.rs index 82341bc..d10b1d2 100644 --- a/datasketches/src/thetafamily/theta/union.rs +++ b/datasketches/src/thetafamily/theta/union.rs @@ -41,13 +41,13 @@ impl UnionMergePolicy for NoopUnionPolicy { } impl ThetaUnion { - /// Update this union with a given sketch. + /// Updates this union with the given sketch. pub fn update<'a>(&mut self, sketch: impl Into>) -> Result<(), Error> { let sketch = sketch.into(); self.state.update(sketch) } - /// Return this union as a compact sketch. + /// Returns this union as a compact sketch. pub fn to_sketch(&self, ordered: bool) -> CompactThetaSketch { let parts = self.state.to_compact_parts(ordered); CompactThetaSketch::from_parts( @@ -63,7 +63,7 @@ impl ThetaUnion { ) } - /// Reset the union to empty state. + /// Resets the union to its empty state. pub fn reset(&mut self) { self.state.reset(); } @@ -95,11 +95,11 @@ impl Default for ThetaUnionBuilder { } impl ThetaUnionBuilder { - /// Set lg_k (log2 of nominal size k). + /// Sets `lg_k`, the base-2 logarithm of the nominal capacity. /// /// # Panics /// - /// If lg_k is not in range [5, 26] + /// Panics if `lg_k` is outside `[5, 26]`. /// /// # Examples /// @@ -117,17 +117,17 @@ impl ThetaUnionBuilder { self } - /// Set resize factor. + /// Sets the resize factor. pub fn resize_factor(mut self, factor: ResizeFactor) -> Self { self.resize_factor = factor; self } - /// Set sampling probability. + /// Sets the sampling probability. /// /// # Panics /// - /// Panics if probability is not in range `(0.0, 1.0]` + /// Panics if `probability` is outside `(0.0, 1.0]`. /// /// # Examples /// @@ -147,7 +147,7 @@ impl ThetaUnionBuilder { self } - /// Set hash seed. + /// Sets the hash seed. /// /// # Examples /// @@ -161,7 +161,7 @@ impl ThetaUnionBuilder { self } - /// Build the ThetaUnion. + /// Builds the [`ThetaUnion`]. /// /// # Examples /// diff --git a/datasketches/src/thetafamily/tuple/a_not_b.rs b/datasketches/src/thetafamily/tuple/a_not_b.rs index f14ebf3..dbe6c3b 100644 --- a/datasketches/src/thetafamily/tuple/a_not_b.rs +++ b/datasketches/src/thetafamily/tuple/a_not_b.rs @@ -77,7 +77,7 @@ impl TupleANotB { /// /// The result retains every key of `a` (below the combined theta) that is not present in `b`, /// keeping the summaries from `a`. Summary values in `b` are ignored and need not be - /// cloneable. If `ordered` is true, the retained entries are sorted ascending by hash. + /// cloneable. If `ordered` is `true`, the retained entries are sorted ascending by hash. /// /// # Errors /// diff --git a/datasketches/src/thetafamily/tuple/hash_table.rs b/datasketches/src/thetafamily/tuple/hash_table.rs index 00e0fec..04b26f6 100644 --- a/datasketches/src/thetafamily/tuple/hash_table.rs +++ b/datasketches/src/thetafamily/tuple/hash_table.rs @@ -45,7 +45,7 @@ impl TupleEntry { Self { hash, summary } } - /// Return the hash used as this entry's key. + /// Returns the hash used as this entry's key. pub fn hash(&self) -> u64 { self.hash.get() } @@ -72,9 +72,9 @@ impl SketchEntry for TupleEntry { impl TupleHashTable { /// Hashes a key and inserts or updates its summary via a single callback. /// - /// See [`try_insert_hash`](Self::try_insert_hash) for the callback contract. Returns true if a - /// new entry was created, false if the key already existed or the hash was screened out by - /// theta. + /// See [`try_insert_hash`](Self::try_insert_hash) for the callback contract. Returns `true` if + /// a new entry was created, or `false` if the key already existed or the hash was screened + /// out by theta. pub fn try_insert(&mut self, key: T, f: F) -> bool where T: Hash, @@ -86,8 +86,8 @@ impl TupleHashTable { /// Inserts or updates the summary slot for a pre-hashed key. /// - /// Returns true if a new entry was created, false otherwise (existing key, declined insertion, - /// or a hash screened out by theta). + /// Returns `true` if a new entry was created, or `false` otherwise (existing key, declined + /// insertion, or a hash screened out by theta). pub fn try_insert_hash(&mut self, hash: u64, f: F) -> bool where F: FnOnce(Option<&mut S>) -> Option, diff --git a/datasketches/src/thetafamily/tuple/intersection.rs b/datasketches/src/thetafamily/tuple/intersection.rs index 273d795..a93712c 100644 --- a/datasketches/src/thetafamily/tuple/intersection.rs +++ b/datasketches/src/thetafamily/tuple/intersection.rs @@ -140,7 +140,7 @@ where /// Returns the intersection result as a compact Tuple sketch. /// - /// If `ordered` is true, retained entries are sorted ascending by hash. + /// If `ordered` is `true`, retained entries are sorted ascending by hash. /// /// # Panics /// diff --git a/datasketches/src/thetafamily/tuple/mod.rs b/datasketches/src/thetafamily/tuple/mod.rs index fa90d21..c159d35 100644 --- a/datasketches/src/thetafamily/tuple/mod.rs +++ b/datasketches/src/thetafamily/tuple/mod.rs @@ -17,10 +17,10 @@ //! Tuple sketch implementation. //! -//! A Tuple sketch is an extension of the Theta sketch: in addition to the retained -//! hash values it keeps a user-defined summary associated with every retained key. The hash table -//! mechanics (theta screening, resize, rebuild to nominal size k) mirror the Theta sketch, with the -//! added requirement that colliding keys merge their summaries. +//! A Tuple sketch is an extension of the Theta sketch: in addition to the retained hash values it +//! keeps a user-defined summary associated with every retained key. The hash table mechanics +//! (theta screening, resize, rebuild to the capacity configured by `lg_k`) mirror the Theta sketch, +//! with the added requirement that colliding keys merge their summaries. //! //! Custom summary behavior is supplied externally through policy objects: [`SummaryPolicy`] //! creates summaries, while [`SummaryUpdatePolicy`] folds update values into them. Summaries that diff --git a/datasketches/src/thetafamily/tuple/sketch.rs b/datasketches/src/thetafamily/tuple/sketch.rs index aafb0c3..8cb9c53 100644 --- a/datasketches/src/thetafamily/tuple/sketch.rs +++ b/datasketches/src/thetafamily/tuple/sketch.rs @@ -300,12 +300,12 @@ where num_retained / theta } - /// Returns theta as a fraction (0.0 to 1.0). + /// Returns theta as a fraction in `[0.0, 1.0]`. pub fn theta(&self) -> f64 { self.table.theta() as f64 / MAX_THETA as f64 } - /// Returns theta as `u64`. + /// Returns theta as a `u64`. pub fn theta64(&self) -> u64 { self.table.theta() } @@ -315,12 +315,12 @@ where self.table.seed_hash() } - /// Returns true if the sketch is empty. + /// Returns `true` if the sketch is empty. pub fn is_empty(&self) -> bool { self.table.is_empty() } - /// Returns true if the sketch is in estimation mode. + /// Returns `true` if the sketch is in estimation mode. pub fn is_estimation_mode(&self) -> bool { self.table.theta() < MAX_THETA } @@ -330,12 +330,12 @@ where self.table.num_retained() } - /// Returns lg_k (log2 of the nominal size k). + /// Returns the configured `lg_k`. pub fn lg_k(&self) -> u8 { self.table.lg_nom_size() } - /// Trims the sketch to the nominal size k. + /// Trims the sketch to the capacity configured by `lg_k`. pub fn trim(&mut self) { self.table.trim(); } @@ -384,9 +384,9 @@ where P: SummaryPolicy, P::Summary: Clone, { - /// Returns this sketch in compact (immutable) form. + /// Returns this sketch in compact, immutable form. /// - /// If `ordered` is true, retained entries are sorted by hash in ascending order. + /// If `ordered` is `true`, retained entries are sorted by hash in ascending order. /// /// # Examples /// @@ -471,12 +471,12 @@ impl CompactTupleSketch { self.theta } - /// Returns true if the sketch is empty. + /// Returns `true` if the sketch is empty. pub fn is_empty(&self) -> bool { self.empty } - /// Returns true if the sketch is in estimation mode. + /// Returns `true` if the sketch is in estimation mode. pub fn is_estimation_mode(&self) -> bool { self.theta < MAX_THETA } @@ -486,7 +486,7 @@ impl CompactTupleSketch { self.entries.len() } - /// Returns true if retained entries are ordered (sorted ascending by hash). + /// Returns `true` if retained entries are ordered (sorted ascending by hash). pub fn is_ordered(&self) -> bool { self.ordered } @@ -765,11 +765,11 @@ where } } - /// Sets lg_k (log2 of the nominal size k). + /// Sets `lg_k`, the base-2 logarithm of the nominal capacity. /// /// # Panics /// - /// Panics if lg_k is not in range [5, 26]. + /// Panics if `lg_k` is outside `[5, 26]`. pub fn lg_k(mut self, lg_k: u8) -> Self { assert!( (MIN_LG_K..=MAX_LG_K).contains(&lg_k), @@ -785,11 +785,11 @@ where self } - /// Sets the sampling probability p. + /// Sets the sampling probability. /// /// # Panics /// - /// Panics if p is not in range `(0.0, 1.0]`. + /// Panics if `probability` is outside `(0.0, 1.0]`. pub fn sampling_probability(mut self, probability: f32) -> Self { assert!( (0.0..=1.0).contains(&probability) && probability > 0.0, diff --git a/datasketches/src/thetafamily/tuple/union.rs b/datasketches/src/thetafamily/tuple/union.rs index 788d418..25bef18 100644 --- a/datasketches/src/thetafamily/tuple/union.rs +++ b/datasketches/src/thetafamily/tuple/union.rs @@ -99,7 +99,7 @@ where /// Returns the union as a [`CompactTupleSketch`]. /// - /// If `ordered` is true, retained entries are sorted ascending by hash. + /// If `ordered` is `true`, retained entries are sorted ascending by hash. pub fn to_sketch(&self, ordered: bool) -> CompactTupleSketch where P::Summary: Clone, @@ -168,11 +168,11 @@ where } } - /// Sets lg_k (log2 of the nominal size k). + /// Sets `lg_k`, the base-2 logarithm of the nominal capacity. /// /// # Panics /// - /// Panics if lg_k is not in range [5, 26]. + /// Panics if `lg_k` is outside `[5, 26]`. pub fn lg_k(mut self, lg_k: u8) -> Self { assert!( (MIN_LG_K..=MAX_LG_K).contains(&lg_k), @@ -188,11 +188,11 @@ where self } - /// Sets the sampling probability p. + /// Sets the sampling probability. /// /// # Panics /// - /// Panics if p is not in range `(0.0, 1.0]`. + /// Panics if `probability` is outside `(0.0, 1.0]`. pub fn sampling_probability(mut self, probability: f32) -> Self { assert!( (0.0..=1.0).contains(&probability) && probability > 0.0,