fix(numtower): a nonzero ExactSum is never negative zero (improvise-z2vr)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
Claude (dbsp-delivery)
2026-10-10 12:11:47 -07:00
committed by Edward Langley
parent 19cea8eded
commit e3f5cee29a
3 changed files with 21 additions and 6 deletions
+8
View File
@@ -485,3 +485,11 @@ and both properties, since one `+0.0` or one cancelling pair must make the zero
Adds `keep` and `gone`, then retracts `gone`; the read and the sum itself must equal a fresh sum
of `keep`. It is why both counters are net weights and why `PartialEq` compares the sign.
### a_sum_that_is_not_zero_never_reads_as_negative_zero
The first version of the sign rule returned `-0.0` whenever the `-0.0` count was positive and the
other count was nil, without checking that the finite total was zero. The weights here (+5.0 and -7.0
net to one "other" addend, and the `-0.0` is held) make the counts say "negative zero" over a total of
-2. Found by the existing `the_accumulator_reads_the_exact_sum_or_its_stated_roundings`, which read
`#i-0.0` for a nonzero sum; the rival is that version.
+4 -6
View File
@@ -40,9 +40,7 @@ impl PartialEq for ExactSum {
propagate(&mut mine);
propagate(&mut theirs);
let counts = |s: &ExactSum| (s.nan, s.pos_inf, s.neg_inf);
mine == theirs
&& counts(self) == counts(o)
&& self.negative_zero() == o.negative_zero()
mine == theirs && counts(self) == counts(o) && self.negative_zero() == o.negative_zero()
}
}
@@ -148,9 +146,9 @@ impl ExactSum {
(true, _, _) | (false, true, true) => f64::NAN,
(false, true, false) => f64::INFINITY,
(false, false, true) => f64::NEG_INFINITY,
(false, false, false) => match self.negative_zero() {
true => -0.0,
false => ratio_to_f64(&self.total(), &(BigInt::one() << 1074)),
(false, false, false) => match (self.negative_zero(), self.total()) {
(true, total) if total.is_zero() => -0.0,
(_, total) => ratio_to_f64(&total, &(BigInt::one() << 1074)),
},
}
}
+9
View File
@@ -78,3 +78,12 @@ proptest! {
prop_assert_eq!(sum, fresh);
}
}
#[test]
fn a_sum_that_is_not_zero_never_reads_as_negative_zero() {
let mut sum = ExactSum::new();
sum.add(-0.0, 1);
sum.add(5.0, 1);
sum.add(7.0, -1);
assert_eq!(sum.value(), -2.0);
}