tisonkun opened a new pull request, #287:
URL: https://github.com/apache/datasketches-rust/pull/287

   Finite samples near the limits of `f64` can make T-Digest rank/CDF/PMF 
queries return NaN or infinity. Large cumulative weights can also make 
quantiles non-monotonic or escape their interpolation interval. This draft 
centralizes the numerical rules for these operations and fixes a separate 
compression error where an extremely unequal weight ratio loses a centroid's 
contribution.
   
   The changes are split into two commits for review:
   
   - **Query arithmetic:** keep cumulative weights in `u64`, use a consistent 
centroid-center calculation, and share bounded interpolation and an 
overflow-safe inverse interpolation. Single-centroid images retain their stored 
extrema, and tail selection uses the same centers as the main scan.
   - **Centroid means:** reuse bounded interpolation, anchored at the heavier 
centroid. For example, merging `(mean=1, weight=2^54)` with `(mean=1e300, 
weight=1)` can previously produce `0` during reverse compression; the result 
now retains the light sample's contribution, approximately `5.55e283`.
   
   This follows the centroid-mean and interpolation model in the [T-Digest 
paper, §2.1 and §2.9](https://arxiv.org/html/1902.04023#S2.SS9), using the 
finite, bounded interpolation approach described in [WG21 
P0811R3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0811r3.html).
 It keeps the existing scale function, compression policy, singleton rules, 
public API, and serialized layout. The production implementation grows by 13 
lines overall, with no new dependency, stored state, or allocation.
   
   Validation compares against `db0703e3a1edc6a8e768361911a3cf7be9ac038e`. A 
temporary deterministic public-API driver exercised 538,672 scenarios and about 
89.7 million query checks. Each row below counts scenarios with at least one 
numerical invariant violation, not individual failures:
   
   | Workload | Scenarios | Before | After |
   | --- | ---: | ---: | ---: |
   | Ordinary synthetic distributed aggregation | 4,032 | 0 | 0 |
   | Native extreme finite inputs | 2,160 | 423 | 0 |
   | Extreme accepted serialized states | 266,240 | 205,213 | 0 |
   | Those states with a subsequent merge where the total weight permits | 
266,240 | 163,538 | 0 |
   
   The ordinary workloads include uniform values, long tails, repeated values, 
signed deltas, timestamps, bimodal data, large counters, and constants, with 
reordered inputs, multiple compression parameters, serialized partials, and 
linear/tree merges. The extreme states exercise subnormals, opposite-sign 
limits, adjacent representable values, and counts around `2^52`, `2^53`, 
`2^54`, and `u64::MAX`; these accepted images are deliberately broader than 
states ordinarily generated by the current scale function. Checks cover 
finite/bounded/monotonic queries, exact stored endpoints, scalar/batch 
agreement with reversed and duplicate ranks, valid PMFs, and serialization 
round trips.
   
   The maximum empirical rank error in each ordinary test case is unchanged. 
This is a numerical robustness change, not a uniform statistical-accuracy 
improvement: a few subnormal `k=10` cases have slightly larger approximation 
error. Permanent coverage adds focused public-API regressions and 128 
QuickCheck cases for finite floating-point bit patterns through serialized 
partial aggregation; the stress driver is not added to the test suite.
   
   - `cargo x prepare-testdata`, `cargo x check`, `cargo x test` (722 tests 
including doctests), and `cargo x lint` passed.
   - Rust 1.86.0: all 34 T-Digest behavior tests passed.
   - C++/Java/Go serialization compatibility and existing-image round trips 
passed. Five construction fingerprints changed: each has one rounded centroid 
mean change, at most about `1.8e-15` in these fixtures; headers, weights, 
lengths, and centroid counts are identical.
   - Existing Divan benchmarks, three alternating paired runs on Apple M4 Max: 
median scalar quantile `134.5 -> 73.3 ns`, rank `47.9 -> 31.7 ns`, sorted batch 
of 100 ranks `300 -> 323.5 ns`, initial compression `16.08 -> 16.78 µs`, and 
merging partials `99.47 -> 106.8 µs`. These short local measurements show the 
tradeoff; they are not a general performance guarantee.
   


-- 
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