BZ #15536: Fix ulp for 128-bit IBM long double.
In 128-bit IBM long double the precision of the type decreases as you approach subnormal numbers, equaling that of a double for subnormal numbers. Therefore adjust the computation in ulp to use 2^(MIN_EXP - MANT_DIG) which is correct for FP_SUBNORMAL for all types.
This commit is contained in:
parent
3b3c4d40c1
commit
8b0ccb2d7f
@ -1,3 +1,11 @@
|
||||
2013-06-03 Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
[BZ #15536]
|
||||
* math/libm-test.inc (MAX_EXP): Remove
|
||||
(MIN_EXP): Define.
|
||||
(ulp): Use MIN_EXP - MANT_DIG.
|
||||
(check_ulp): Verify subnormal ulps. Only allow a range of +/- 1 ulp.
|
||||
|
||||
2013-05-31 Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
* po/be.po: Revert last change.
|
||||
|
2
NEWS
2
NEWS
@ -19,7 +19,7 @@ Version 2.18
|
||||
15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380, 15381, 15394,
|
||||
15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423, 15424, 15426,
|
||||
15429, 15441, 15442, 15448, 15465, 15480, 15485, 15488, 15490, 15493,
|
||||
15497, 15506, 15529, 15553.
|
||||
15497, 15506, 15529, 15536, 15553.
|
||||
|
||||
* CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla
|
||||
#15078).
|
||||
|
@ -269,8 +269,8 @@ static FLOAT max_error, real_max_error, imag_max_error;
|
||||
|
||||
#define MANT_DIG CHOOSE ((LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1), \
|
||||
(LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1))
|
||||
#define MAX_EXP CHOOSE ((LDBL_MAX_EXP-1), (DBL_MAX_EXP-1), (FLT_MAX_EXP-1), \
|
||||
(LDBL_MAX_EXP-1), (DBL_MAX_EXP-1), (FLT_MAX_EXP-1))
|
||||
#define MIN_EXP CHOOSE ((LDBL_MIN_EXP-1), (DBL_MIN_EXP-1), (FLT_MIN_EXP-1), \
|
||||
(LDBL_MIN_EXP-1), (DBL_MIN_EXP-1), (FLT_MIN_EXP-1))
|
||||
|
||||
/* Compare KEY (a string, with the name of a test or a function) with
|
||||
ULP (a pointer to a struct ulp_data structure), returning a value
|
||||
@ -680,7 +680,7 @@ ulp (FLOAT value)
|
||||
/* Fall through... */
|
||||
case FP_SUBNORMAL:
|
||||
/* The next closest subnormal value is a constant distance away. */
|
||||
ulp = FUNC(ldexp) (1.0, 1 - (MAX_EXP + MANT_DIG));
|
||||
ulp = FUNC(ldexp) (1.0, MIN_EXP - MANT_DIG);
|
||||
break;
|
||||
|
||||
case FP_NORMAL:
|
||||
@ -14583,7 +14583,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
void
|
||||
check_ulp (void)
|
||||
{
|
||||
FLOAT ulps, value;
|
||||
FLOAT ulps, ulpx, value;
|
||||
int i;
|
||||
/* Check ulp of zero is a subnormal value... */
|
||||
ulps = ulp (0x0.0p0);
|
||||
@ -14599,30 +14599,45 @@ check_ulp (void)
|
||||
fprintf (stderr, "ulp (1.0L) is not FP_NORMAL\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Compute the next subnormal value using nextafter to validate ulp.
|
||||
We allow +/- 1 ulp around the represented value. */
|
||||
value = FUNC(nextafter) (0, 1);
|
||||
ulps = ULPDIFF (value, 0);
|
||||
ulpx = ulp (1.0L);
|
||||
if (ulps < (1.0L - ulpx) || ulps > (1.0L + ulpx))
|
||||
{
|
||||
fprintf (stderr, "Value outside of 1 +/- 1ulp.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
/* Compute the nearest representable number from 10 towards 20.
|
||||
The result is 10 + 1ulp. We use this to check the ulp function. */
|
||||
The result is 10 + 1ulp. We use this to check the ulp function.
|
||||
We allow +/- 1 ulp around the represented value. */
|
||||
value = FUNC(nextafter) (10, 20);
|
||||
ulps = ULPDIFF (value, 10);
|
||||
if (ulps > 1.0L)
|
||||
ulpx = ulp (1.0L);
|
||||
if (ulps < (1.0L - ulpx) || ulps > (1.0L + ulpx))
|
||||
{
|
||||
fprintf (stderr, "The value of ulp (10+1ulp,10) is greater than 1 ulp.\n");
|
||||
fprintf (stderr, "Value outside of 1 +/- 1ulp.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
/* This gives one more ulp. */
|
||||
value = FUNC(nextafter) (value, 20);
|
||||
ulps = ULPDIFF (value, 10);
|
||||
if (ulps > 2.0L)
|
||||
ulpx = ulp (2.0L);
|
||||
if (ulps < (2.0L - ulpx) || ulps > (2.0L + ulpx))
|
||||
{
|
||||
fprintf (stderr, "The value of ulp (10+2ulp,10) is greater than 2 ulp.\n");
|
||||
fprintf (stderr, "Value outside of 2 +/- 1ulp.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
/* And now calculate 100 ulp. */
|
||||
for (i = 2; i < 100; i++)
|
||||
value = FUNC(nextafter) (value, 20);
|
||||
ulps = ULPDIFF (value, 10);
|
||||
if (ulps > 100.0L)
|
||||
ulpx = ulp (100.0L);
|
||||
if (ulps < (100.0L - ulpx) || ulps > (100.0L + ulpx))
|
||||
{
|
||||
fprintf (stderr, "The value of ulp (10+100ulp,10) is greater than 100 ulp.\n");
|
||||
fprintf (stderr, "Value outside of 100 +/- 1ulp.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user