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:
committed by
Edward Langley
parent
19cea8eded
commit
e3f5cee29a
@@ -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.
|
||||
|
||||
@@ -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)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user