mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-08 23:58:31 +08:00
The reference implementation used to verify the a and A conversions assumed the value it was given was normal, splitting it into a significand of the full width and an exponent. That is not true below the smallest normal value, where the exponent can go no lower and the significand loses bits from the top instead, which is what makes the leading hexadecimal digit of a subnormal come out as zero. Given a subnormal it would have produced a normalized result such as 0x1p-1070 where we print 0x0.000000000001p-1022. Telling the two apart needs the minimum exponent for the type, which was not among the data the test program supplies, so add it as a MINEXP definition reported in a record of its own next to the working precision. Then stop normalizing once that exponent is reached, and pad the digits produced on the left, as there are no longer enough of them to fill the field on their own. The remaining conversions are unaffected: they work from the value itself and never needed it decomposed. How far the exponent has to be shifted to sit after the significand depends on the working precision, so hold MINEXP as reported and combine the two only once a value is due to be converted, rather than requiring the records to arrive in a particular order. Where no MINEXP record arrives the type has no subnormals and no clamping is applied. None of the values iterated over were subnormal, so this could not be observed. Add DBL_TRUE_MIN and LDBL_TRUE_MIN to cover it, which also exercises the smallest exponent with the remaining conversions. How many bits the leading hexadecimal digit holds varies with the type, one for a 53 bit significand and four for a 64 bit one, so both are needed: the wider case lands on a different exponent than the minimum for the type, with LDBL_TRUE_MIN coming out as 0x0.000000000000001p-16385 rather than at the p-16382 that the leading digit of a normal value would sit at. One sign is enough for either, as nothing in the sign handling depends on the value being subnormal, and the records these produce are among the most expensive in the test suite. Tested on x86_64-linux-gnu, where all 672 results pass. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
37 lines
1.3 KiB
C
37 lines
1.3 KiB
C
/* Test skeleton for formatted printf output for double conversions.
|
|
Copyright (C) 2024-2026 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
#include <float.h>
|
|
#include <math.h>
|
|
|
|
#define MID_WIDTH 20
|
|
#define HUGE_WIDTH 320
|
|
/* Full-precision output runs to hundreds of digits here. */
|
|
#define TST_PRINTF_WIDE_TYPE 1
|
|
#define REF_FMT ".35e"
|
|
#define REF_VAL(v) (v)
|
|
#define PREC DBL_MANT_DIG
|
|
#define MINEXP DBL_MIN_EXP
|
|
typedef double type_t;
|
|
static const type_t vals[] =
|
|
{ -HUGE_VAL, -DBL_MAX, -DBL_MIN, -0.0, -NAN, NAN, 0, DBL_TRUE_MIN,
|
|
DBL_MIN, 99.9, DBL_MAX, HUGE_VAL };
|
|
static const char length[] = "";
|
|
|
|
#include "tst-printf-format-skeleton.c"
|