On Wed, 7 Jun 2023 at 18:26, Jonathan Wakely <jwakely....@gmail.com> wrote:

>
>
> On Wed, 7 Jun 2023, 18:17 Jakub Jelinek via Libstdc++, <
> libstd...@gcc.gnu.org> wrote:
>
>> Hi!
>>
>> This test apparently contains 3 problematic floating point constants,
>> 1e126, 4.91e-6 and 5.547e-6.  These constants suffer from double rounding
>> when -fexcess-precision=standard evaluates double constants in the
>> precision
>> of Intel extended 80-bit long double.
>> As written in the PR, e.g. the first one is
>> 0x1.7a2ecc414a03f7ff6ca1cb527787b130a97d51e51202365p+418
>> in the precision of GCC's internal format, 80-bit long double has
>> 63-bit precision, so the above constant rounded to long double is
>> 0x1.7a2ecc414a03f800p+418L
>> (the least significant bit in the 0 before p isn't there already).
>> 0x1.7a2ecc414a03f800p+418L rounded to IEEE double is
>> 0x1.7a2ecc414a040p+418.
>> Now, if excess precision doesn't happen and we round the GCC's internal
>> format number directly to double, it is
>> 0x1.7a2ecc414a03fp+418 and that is the number the test expects.
>> One can see it on x86-64 (where excess precision to long double doesn't
>> happen) where double(1e126L) != 1e126.
>> The other two constants suffer from the same problem.
>>
>> The following patch tweaks the testcase, such that those problematic
>> constants are used only if FLT_EVAL_METHOD is 0 or 1 (i.e. when we have
>> guarantee the constants will be evaluated in double precision),
>> plus adds corresponding tests with hexadecimal constants which don't
>> suffer from this excess precision problem, they are exact in double
>> and long double can hold all double values.
>>
>> Bootstrapped/regtested on x86_64-linux and i686-linux, additionally
>> tested on the latter with
>> make check RUNTESTFLAGS='--target_board=unix/-fexcess-precision=standard
>> conformance.exp=to_chars/double.cc'
>> Ok for trunk?
>>
>
> Yes, OK.
>
> Thanks for solving this puzzle!
>

I think this would be good for gcc-13, as that has the new
-fexcess-precision semantics for -std=c++NN too, right?


>
>
>
>> 2023-06-07  Jakub Jelinek  <ja...@redhat.com>
>>
>>         PR libstdc++/110145
>>         * testsuite/20_util/to_chars/double.cc: Include <cfloat>.
>>         (double_to_chars_test_cases,
>>         double_scientific_precision_to_chars_test_cases_2,
>>         double_fixed_precision_to_chars_test_cases_2): #if out 1e126,
>> 4.91e-6
>>         and 5.547e-6 tests if FLT_EVAL_METHOD is negative or larger than
>> 1.
>>         Add unconditional tests with corresponding double constants
>>         0x1.7a2ecc414a03fp+418, 0x1.4981285e98e79p-18 and
>>         0x1.7440bbff418b9p-18.
>>
>> --- libstdc++-v3/testsuite/20_util/to_chars/double.cc.jj
>> 2022-11-03 22:16:08.542329555 +0100
>> +++ libstdc++-v3/testsuite/20_util/to_chars/double.cc   2023-06-07
>> 15:41:44.275604870 +0200
>> @@ -40,6 +40,7 @@
>>  #include <cstring>
>>  #include <limits>
>>  #include <optional>
>> +#include <cfloat>
>>
>>  #include <testsuite_hooks.h>
>>
>> @@ -1968,9 +1969,19 @@ inline constexpr double_to_chars_testcas
>>      {1e125, chars_format::fixed,
>>
>>  
>> "9999999999999999248677616189928820425446708698348384614392259722252941999757930266031634937628176537515300"
>>          "5841365553228283904"},
>> +#if FLT_EVAL_METHOD >= 0 && FLT_EVAL_METHOD <= 1
>> +    // When long double is Intel extended and double constants are
>> evaluated in precision of
>> +    // long double, this value is initialized to double(1e126L), which
>> is 0x1.7a2ecc414a040p+418 due to
>> +    // double rounding of 0x1.7a2ecc414a03f7ff6p+418L first to
>> 0x1.7a2ecc414a03f800p+418L and
>> +    // then to 0x1.7a2ecc414a040p+418, while when double constants are
>> evaluated in precision of
>> +    // IEEE double, this is 0x1.7a2ecc414a03fp+418 which the test
>> expects.  See PR110145.
>>      {1e126, chars_format::fixed,
>>
>>  
>> "9999999999999999248677616189928820425446708698348384614392259722252941999757930266031634937628176537515300"
>>          "58413655532282839040"},
>> +#endif
>> +    {0x1.7a2ecc414a03fp+418, chars_format::fixed,
>> +
>>  
>> "9999999999999999248677616189928820425446708698348384614392259722252941999757930266031634937628176537515300"
>> +       "58413655532282839040"},
>>      {1e127, chars_format::fixed,
>>
>>  
>> "9999999999999999549291066784979473595300225087383524118479625982517885450291174622154390152298057300868772"
>>          "377386949310916067328"},
>> @@ -2816,8 +2827,12 @@ inline constexpr double_to_chars_testcas
>>      {0x1.a6c767640cd71p+879, chars_format::scientific,
>> "6.6564021122018745e+264"},
>>
>>      // Incorrectly handled by dtoa_milo() (Grisu2), which doesn't
>> achieve shortest round-trip.
>> +#if FLT_EVAL_METHOD >= 0 && FLT_EVAL_METHOD <= 1
>>      {4.91e-6, chars_format::scientific, "4.91e-06"},
>>      {5.547e-6, chars_format::scientific, "5.547e-06"},
>> +#endif
>> +    {0x1.4981285e98e79p-18, chars_format::scientific, "4.91e-06"},
>> +    {0x1.7440bbff418b9p-18, chars_format::scientific, "5.547e-06"},
>>
>>      // Test hexfloat corner cases.
>>      {0x1.728p+0, chars_format::hex, "1.728p+0"}, // instead of "2.e5p-1"
>> @@ -5537,10 +5552,16 @@ inline constexpr double_to_chars_testcas
>>          "9."
>>
>>  
>> "9999999999999992486776161899288204254467086983483846143922597222529419997579302660316349376281765375153005"
>>          "841365553228283904e+124"},
>> +#if FLT_EVAL_METHOD >= 0 && FLT_EVAL_METHOD <= 1
>>      {1e+126, chars_format::scientific, 124,
>>          "9."
>>
>>  
>> "9999999999999992486776161899288204254467086983483846143922597222529419997579302660316349376281765375153005"
>>          "841365553228283904e+125"},
>> +#endif
>> +    {0x1.7a2ecc414a03fp+418, chars_format::scientific, 124,
>> +       "9."
>> +
>>  
>> "9999999999999992486776161899288204254467086983483846143922597222529419997579302660316349376281765375153005"
>> +       "841365553228283904e+125"},
>>      {1e+127, chars_format::scientific, 126,
>>          "9."
>>
>>  
>> "9999999999999995492910667849794735953002250873835241184796259825178854502911746221543901522980573008687723"
>> @@ -29579,9 +29600,14 @@ inline constexpr double_to_chars_testcas
>>      {1e+125, chars_format::fixed, 0,
>>
>>  
>> "9999999999999999248677616189928820425446708698348384614392259722252941999757930266031634937628176537515300"
>>          "5841365553228283904"},
>> +#if FLT_EVAL_METHOD >= 0 && FLT_EVAL_METHOD <= 1
>>      {1e+126, chars_format::fixed, 0,
>>
>>  
>> "9999999999999999248677616189928820425446708698348384614392259722252941999757930266031634937628176537515300"
>>          "58413655532282839040"},
>> +#endif
>> +    {0x1.7a2ecc414a03fp+418, chars_format::fixed, 0,
>> +
>>  
>> "9999999999999999248677616189928820425446708698348384614392259722252941999757930266031634937628176537515300"
>> +       "58413655532282839040"},
>>      {1e+127, chars_format::fixed, 0,
>>
>>  
>> "9999999999999999549291066784979473595300225087383524118479625982517885450291174622154390152298057300868772"
>>          "377386949310916067328"},
>>
>>         Jakub
>>
>>

Reply via email to