nexttoward(3): Fix high-word test on small positive subnormals.

By this point in the logic, x can't be zero, so it's either positive
or negative.

The high word hx, however, can be zero, when x is a small positive
subnormal.  This means x is a small positive subnormal, so if x > y
we are computing nextDown, and if x < y we are computing nextUp.

hx is a (signed 32-bit) integer, not a double floating-point number,
so it's a little silly to compare hx > 0.0.  But that on its own
isn't enough to trigger the bug because all signed 32-bit integers
can be represented by double on all NetBSD architectures.

PR lib/58236
This commit is contained in:
riastradh 2024-05-11 02:07:53 +00:00
parent afce20e57c
commit bcaa0f35c3
2 changed files with 5 additions and 8 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: s_nexttoward.c,v 1.2 2013/08/21 13:03:56 martin Exp $ */
/* $NetBSD: s_nexttoward.c,v 1.3 2024/05/11 02:07:53 riastradh Exp $ */
/* @(#)s_nextafter.c 5.1 93/09/24 */
/*
@ -13,7 +13,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: s_nexttoward.c,v 1.2 2013/08/21 13:03:56 martin Exp $");
__RCSID("$NetBSD: s_nexttoward.c,v 1.3 2024/05/11 02:07:53 riastradh Exp $");
/*
* We assume that a long double has a 15-bit exponent. On systems
@ -71,7 +71,7 @@ nexttoward(double x, long double y)
return x; /* raise underflow flag */
}
if ((hx > 0.0) ^ (x < y)) { /* x -= ulp */
if ((hx >= 0) ^ (x < y)) { /* x -= ulp */
if (lx == 0) hx -= 1;
lx -= 1;
} else { /* x += ulp */

View File

@ -1,4 +1,4 @@
/* $NetBSD: t_next.c,v 1.5 2024/05/11 01:44:12 riastradh Exp $ */
/* $NetBSD: t_next.c,v 1.6 2024/05/11 02:07:54 riastradh Exp $ */
/*-
* Copyright (c) 2024 The NetBSD Foundation, Inc.
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_next.c,v 1.5 2024/05/11 01:44:12 riastradh Exp $");
__RCSID("$NetBSD: t_next.c,v 1.6 2024/05/11 02:07:54 riastradh Exp $");
#include <atf-c.h>
#include <float.h>
@ -391,9 +391,6 @@ ATF_TC_BODY(next_near_0, tc)
#endif
};
#ifdef __HAVE_LONG_DOUBLE
atf_tc_expect_fail("PR 58236: nexttoward(3) is broken on subnormals");
#endif
check(x, __arraycount(x));
}