mirror of
https://github.com/pocketpy/pocketpy
synced 2026-08-07 06:37:10 +08:00
fix(float): abs(-0.0) should return 0.0 (#534)
abs(-0.0) returns -0.0 instead of 0.0, and math.fabs(-0.0) does the same. Both come from the idiom (x < 0) ? -x : x. Since -0.0 < 0 is false, the negative zero is returned unchanged. The idiom appears twice, once in dmath_fabs and once open-coded in float__abs__. Fix dmath_fabs by clearing the sign bit, the same way dmath_copysign just above it works, and make float__abs__ call the shared helper instead of repeating the comparison. abs(-0.0) == 0.0 is true even with the bug, because -0.0 == 0.0 under IEEE 754, so the added tests compare str(...) to check the sign.
This commit is contained in:
parent
005550e92a
commit
7fd7e2db15
@ -384,7 +384,7 @@ static bool int__abs__(int argc, py_Ref argv) {
|
||||
static bool float__abs__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_f64 val = py_tofloat(&argv[0]);
|
||||
py_newfloat(py_retval(), val < 0 ? -val : val);
|
||||
py_newfloat(py_retval(), dmath_fabs(val));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -701,8 +701,11 @@ double dmath_copysign(double x, double y) {
|
||||
return ux.f;
|
||||
}
|
||||
|
||||
// https://github.com/kraj/musl/blob/kraj/master/src/math/fabs.c
|
||||
double dmath_fabs(double x) {
|
||||
return (x < 0) ? -x : x;
|
||||
union Float64Bits u = { .f = x };
|
||||
u.i &= -1ULL/2;
|
||||
return u.f;
|
||||
}
|
||||
|
||||
double dmath_ceil(double x) {
|
||||
|
||||
@ -97,6 +97,9 @@ assert 3.4e+3 == 3400.0
|
||||
assert abs(1.0) == 1.0
|
||||
assert abs(-1.0) == 1.0
|
||||
assert abs(0.0) == 0.0
|
||||
# abs(-0.0) is 0.0, not -0.0. `==` cannot tell them apart, so check the sign.
|
||||
assert str(abs(-0.0)) == '0.0'
|
||||
assert str(abs(0.0)) == '0.0'
|
||||
|
||||
# import math
|
||||
# assert math.isnan(0/0)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user