tisonkun commented on PR #772:
URL: 
https://github.com/apache/datasketches-java/pull/772#issuecomment-5861603990

   @leerho While evaluating the corresponding Rust change 
(apache/datasketches-rust#283), I would like to understand the rationale for 
the empty Theta/Tuple seed-hash rule. Is this an intentional semantic 
distinction, or is the Tuple change primarily following the existing C++ 
encoding?
   
   I have two questions:
   
   1. **What concrete problem does zeroing the seed hash solve?** An empty 
sketch can still have a configured seed. As this PR notes, the existing nonzero 
seed hash is already accepted by the empty Tuple readers, so retaining it does 
not appear to break deserialization compatibility. Writing zero also does not 
reduce the image size. Ignoring an empty input during a set operation and 
discarding its seed fingerprint during serialization seem like separate 
decisions: the former does not require the latter. Is there a documented 
requirement for a unique, seed-independent empty encoding, or another benefit 
that justifies this special case?
   
   2. **Why does this apply specifically to Theta/Tuple?** I checked both the 
Java code at this PR's head and C++ at `70e462f`. Other seeded families 
preserve and validate their configuration even when empty:
   
   | Family | Java | C++ |
   | --- | --- | --- |
   | CPC | [Empty serialization retains the seed 
hash](https://github.com/apache/datasketches-java/blob/1481c3fc76bf78bf79a0d4a3edffba877911694b/src/main/java/org/apache/datasketches/cpc/CompressedState.java#L223-L232);
 [heapify/uncompress validates 
it](https://github.com/apache/datasketches-java/blob/1481c3fc76bf78bf79a0d4a3edffba877911694b/src/main/java/org/apache/datasketches/cpc/CpcSketch.java#L664-L676).
 | [Writes the seed hash before the non-empty payload 
branch](https://github.com/apache/datasketches-cpp/blob/70e462fcd03977e378c34ca121ba9f40d17ecef3/cpc/include/cpc_sketch_impl.hpp#L431-L435);
 [deserialization validates 
it](https://github.com/apache/datasketches-cpp/blob/70e462fcd03977e378c34ca121ba9f40d17ecef3/cpc/include/cpc_sketch_impl.hpp#L580-L585).
 |
   | Count-Min | [Writes the seed hash before returning the empty 
image](https://github.com/apache/datasketches-java/blob/1481c3fc76bf78bf79a0d4a3edffba877911694b/src/main/java/org/apache/datasketches/count/CountMinSketch.java#L416-L425);
 [deserialization checks it before the empty 
return](https://github.com/apache/datasketches-java/blob/1481c3fc76bf78bf79a0d4a3edffba877911694b/src/main/java/org/apache/datasketches/count/CountMinSketch.java#L469-L482).
 | [Writes the seed hash for empty 
images](https://github.com/apache/datasketches-cpp/blob/70e462fcd03977e378c34ca121ba9f40d17ecef3/count/include/count_min_impl.hpp#L294-L303);
 [deserialization checks it before the empty 
return](https://github.com/apache/datasketches-cpp/blob/70e462fcd03977e378c34ca121ba9f40d17ecef3/count/include/count_min_impl.hpp#L331-L343).
 |
   | Bloom | Stores the full seed rather than a seed hash: [empty serialization 
preserves 
it](https://github.com/apache/datasketches-java/blob/1481c3fc76bf78bf79a0d4a3edffba877911694b/src/main/java/org/apache/datasketches/filters/bloomfilter/BloomFilter.java#L819-L837),
 and [union/intersection require 
compatibility](https://github.com/apache/datasketches-java/blob/1481c3fc76bf78bf79a0d4a3edffba877911694b/src/main/java/org/apache/datasketches/filters/bloomfilter/BloomFilter.java#L681-L701),
 including [matching 
seeds](https://github.com/apache/datasketches-java/blob/1481c3fc76bf78bf79a0d4a3edffba877911694b/src/main/java/org/apache/datasketches/filters/bloomfilter/BloomFilter.java#L753-L760).
 | [Empty serialization preserves the full 
seed](https://github.com/apache/datasketches-cpp/blob/70e462fcd03977e378c34ca121ba9f40d17ecef3/filters/include/bloom_filter_impl.hpp#L424-L441);
 [union/intersection check seed compatibility without an empty-input 
exception](https://github.com/apache/dataske
 
tches-cpp/blob/70e462fcd03977e378c34ca121ba9f40d17ecef3/filters/include/bloom_filter_impl.hpp#L855-L878).
 |
   
   CPC is an especially direct contrast: [Java's union checks the seed hash 
before returning for an empty serialized 
input](https://github.com/apache/datasketches-java/blob/1481c3fc76bf78bf79a0d4a3edffba877911694b/src/main/java/org/apache/datasketches/cpc/CpcUnion.java#L303-L306),
 its [object-input path does the same with the 
seed](https://github.com/apache/datasketches-java/blob/1481c3fc76bf78bf79a0d4a3edffba877911694b/src/main/java/org/apache/datasketches/cpc/CpcUnion.java#L350-L355),
 and [C++ also checks before its empty-input 
return](https://github.com/apache/datasketches-cpp/blob/70e462fcd03977e378c34ca121ba9f40d17ecef3/cpc/include/cpc_union_impl.hpp#L104-L112).
 Thus even an empty input can produce a seed-mismatch error in both 
implementations. That is a configuration invariant, despite the empty input 
contributing no data.
   
   I see that [Java Theta uses an empty compact singleton and a fixed byte 
representation](https://github.com/apache/datasketches-java/blob/1481c3fc76bf78bf79a0d4a3edffba877911694b/src/main/java/org/apache/datasketches/theta/EmptyCompactSketch.java#L27-L45).
 Is the intended boundary that immutable compact Theta/Tuple results discard 
seed identity when empty, while updateable sketches retain configuration? Or is 
this a historical format convention that Tuple is following for byte-level 
consistency? The differing policies may be intentional, but it would help to 
state the distinction explicitly rather than infer a general rule that 
emptiness makes the seed irrelevant.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to