Skip to content

quality audit: fix dsu_weighted precision loss; doc typo#227

Merged
cameroncuster merged 1 commit into
devfrom
quality-audit
Jul 6, 2026
Merged

quality audit: fix dsu_weighted precision loss; doc typo#227
cameroncuster merged 1 commit into
devfrom
quality-audit

Conversation

@cameroncuster

Copy link
Copy Markdown
Member

Full audit of every .hpp under library/ (144 files), prioritizing correctness > efficiency > readability. Every candidate finding was verified with a compiled repro before being accepted or rejected. The result is deliberately small: only two changes survived triage.

Changes

1. dsu/dsu_weighted.hpp — correctness: sentinel round-trips through double

// before
return f(u) == f(v) ? d[v] - d[u] : 1e18;
// after
return f(u) == f(v) ? d[v] - d[u] : ll(1e18);

1e18 is a double, so the ternary's common type is double — meaning the d[v] - d[u] branch (the real answer, not just the sentinel) is converted ll → double → ll. Any difference with |w| > 2^53 silently loses precision.

Compiled repro (weight 2^53 + 1 = 9007199254740993):

expected  9007199254740993
fixed     9007199254740993  EXACT
old       9007199254740992  WRONG
randomized checks passed   (10k ops, joins/diffs vs ground truth)

Tests compare against ll(1e18), whose value is unchanged (10^18 is exactly representable), so dsu_weighted_lib_checker / dsu_weighted_aizu behavior is identical for the sentinel path.

2. data_structures_[l,r)/uncommon/deque_op.hpp — doc typo

ammortizedamortized. Comment-only.

Findings investigated and rejected (with verification)

Six parallel reviewers flagged ~20 candidates; each was checked against the actual code/semantics. Notable false positives, so they don't get re-reported later:

  • implicit.hpp "UB on leaf nodes"push on a leaf can't reach the apply(lazy, lch) path: a leaf is only ever fully covered or disjoint, so lazy is consumed by the full-cover apply and children are never touched.
  • distinct_query.hpp "inverted query"pst.query(0, l+1, r) - pst.query(0, l+1, l) is the standard persistent-tree distinct count (versions indexed by right endpoint); verified against the Library Checker test.
  • longest_palindrome_query.hpp "RMQ bounds violation at x = r-l-1" — substituting x gives query(l+r-1, l+r), which satisfies l < r. The reviewer's algebra was off by one.
  • binary_search.hpp "UB dereferencing end()"*end() of an iota_view is well-defined (returns the bound); the doc comment explicitly documents returning hi when no element qualifies.
  • gcd/lcm_convolution "signed underflow UB" — values are in [0, mod); worst case 0 - (mod-1) is far from INT_MIN. (x -= y) < 0 ? x += mod is well-defined and is the codebase-standard reduction.
  • count_paths_triangle.hpp "syntax error vl(mid + all(bottom))"all(x) expands to begin(x), end(x), so this is vl(mid + begin(bottom), end(bottom)): valid, and it compiles in CI today.
  • lcs_dp.hpp "store const T& instead of copying t" — rejected as a lifetime trap: lcs_dp lcs(t) in lcs_queries would be fine today, but the copy is O(m) once vs an O(n·m) algorithm, and a dangling-reference footgun isn't worth it in a hackpack.
  • pass-by-value params (bit_rurq, bit_rupq, wavelet_matrix, compress_tree, xor_conv, get_right_and_top) — all intentional: each function mutates its copy in place (adjacent_difference in-place, fwht in-place, sort+dedup, swap(left, bottom)).
  • solve_linear_mod "silent failure on inconsistent system"sol staying empty is the documented no-solution signal; the test checks empty(info.sol).
  • grow.hpp/mod "link-time conflicts" — headers are single-TU by construction (hackpack), non-issue.

Validation

  • g++ -std=c++20 -O2 -Wall -Wextra and clang++ compile all 6 affected test files (2 dsu_weighted, 4 deque) cleanly
  • tests/scripts/grep_clangformat_cppcheck.sh passes (clang-format + cppcheck, no new suppressions)
  • compiled repro above demonstrates the precision bug and its fix

@cameroncuster cameroncuster merged commit 7334120 into dev Jul 6, 2026
8 checks passed
@cameroncuster cameroncuster deleted the quality-audit branch July 6, 2026 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant