Pull Request №701 RosettaCommons/rosetta/main ← lyskov-ai/rosetta/fix/audit-comparison-and-off-by-one
Merge: dc594471462f126ea60fc1148900ed66e5b77e44←b2883867f98b1a2e01669b1ea8b4321551565904
Fix correctness bugs: broken operator< and off-by-one residue loops
----------------
Merge commit message:
Fix correctness bugs: broken operator< and off-by-one residue loops
Two unrelated families of correctness bugs found by an audit pass.
Continues the patterns from #696 (broken comparison operators) and
#695 (off-by-one residue loops).
Broken operator< implementations (violate strict weak ordering):
* core/environment/LocalPosition.cc: assigned the signed result of
std::string::compare() to the unsigned alias Size, so any
"this->label_ < other.label_" case wrapped to a huge value and the
cmp > 0 branch fired. On top of that, the cmp > 0 branch itself
was inverted relative to "less than". Combined effect: for any
two LocalPositions with distinct labels, both a < b and b < a
returned true. The class is used as the key of
std::map<LocalPosition, core::Real> in CutBiasClaim. Replaced
with std::tie lexicographic compare.
* protocols/environment/claims/ClaimStrength.cc: every comparison
operand was reversed, so operator<(*this, other) returned true
exactly when *this was lexicographically greater than other --
the operator was fully inverted relative to its name and to
operator==. Replaced with std::tie lexicographic compare.
Off-by-one loops over 1-indexed residue / vector1 ranges:
* protocols/simple_moves/ExplicitWaterMover.cc get_water_recovery:
four loops using i < pose.total_residue() (and i < vec.size()
on utility::vector1<>, which is 1-indexed). The last residue and
last vector element were skipped, so water-recovery counts and
the per-water coordinate lists silently dropped the final entry.
* protocols/ligand_docking/GALigandDock/GALigandDock.cc
calculate_free_ligand_score: the loop adding CoordinateConstraints
to anchor every atom used ires < pose->total_residue(), so the
last residue's atoms were not constrained.
* protocols/membrane_benchmark/MembraneEnergyLandscapeSampler.cc
count_res / count_diff: both helpers walked
ii < pose.total_residue(), so a matching last residue was never
counted and a differing last residue's mismatch was never
reported.