gcc 11.1.0: printf("%.43f\n", 0x1.52f8a8e32e982p-140): printed value is incorrectly rounded

Corinna Vinschen vinschen@redhat.com
Mon Nov 29 15:55:32 GMT 2021


Hi Takashi,

On Nov 29 23:24, Takashi Yano wrote:
> On Mon, 29 Nov 2021 19:56:46 +0900
> Takashi Yano wrote:
> > On Sun, 28 Nov 2021 22:16:46 +0900
> > Takashi Yano wrote:
> > > On Sun, 28 Nov 2021 21:38:39 +0900
> > > Takashi Yano wrote:
> > > > On Sun, 28 Nov 2021 16:43:11 +0900
> > > > Takashi Yano wrote:
> > > > > On Thu, 4 Nov 2021 13:24:42 +0100
> > > > > Corinna Vinschen wrote:
> > > > > > However, a much better fix would be to switch to gdtoa, as the BSDs and
> > > > > > Mingw64 do.
> > > > > 
> > > > > I have tried to import gdtoa into newlib from OpenBSD.
> > > > > 
> > > > > gdtoa seems to use malloc much, so it may not work in some of
> > > > > platforms due to insufficient heap. Therefore, new ldtoa.c tries
> > > > > gdtoa first and fallbacks to legacy ldtoa if gdtoa fails.
> > > > > 
> > > > > To import gdtoa to newlib, I did:
> > > > > 1) Create "machine/ieee.h" which conditionally defines ieee_ext
> > > > >    structure and EXT_TO_ARRAY32() macro depend on architecture.
> > > > > 2) Create arith.h which reflects endian of architecture.
> > > > > 3) Merge gdtoa.h with OpenBSD's gdtoa.h. __BEGIN_HIDDEN_DECLS,
> > > > >    __END_HIDDEN_DECLS, PROTO_NORMAL() and DEF_STRONG() are
> > > > >    defined as dummy in this header.
> > > > > 4) Replace malloc()/free() with _malloc_r()/_free_r().
> > > > > 5) Implement ACQUIRE_DTOA_LOCK() and FREE_DTOA_LOCK() macros
> > > > >    using "sys/lock.h" for multi-threading environment.
> > > > > 6) Remove inclusion of "gd_qnan.h" which is not used.
> > > > > 
> > > > > Please see attached patch for more details.
> > > > > 
> > > > > I confirmed this works nicely with cygwin. Moreover, it is much
> > > > > faster than legacy ldtoa (more than 4 times faster).
> > > > > 
> > > > > However, this may break some other supported platforms.
> > > > > 
> > > > > Could anyone please check this?

Thanks for looking into that and the patch...

> > > > 
> > > > Ah, in "machine/ieee.h", struct ieee_ext definition for
> > > > LDBL_MANT_DIG==64 and __IEEE_BIG_ENDIAN case, is obviously
> > > > wrong. 
> > > 
> > > Fixed.
> > 
> > Bit order for ARMEL without __VFP_FP__ is fixed.
> 
> Add support for ARM FPA10 math coprocessor extended precision format.

...and thanks for subsequent patches.

As far as I can see, there are some more generic changes required in the
gdtoa code.  At a first glance I see these problems in terms of reentrancy:

- __ldtoa should take an additional parameter `struct __reent *',
  per the convention as first parameter.

- Balloc/Bfree are already implemented in newlib as reentrent functions,
  taking an additional reent pointer.  Those should be used, rather than
  getting implemented again as non-reentrant functions.

- MALLOC/FREE should be defined as taking the reent pointer given to
  __ldtoa, rather than _REENT.

As for the allocations, how big are those?  If they are comparable with
the allocation we now perform in _ldtoa_r, it might not be worth to keep
both functions.  Some users of smaller targets might also complain that
using printf now always pulls in both variants of ldtoa, thus raising
code size unnecessarily.  It might be better to keep the calls separate
and only use one or the other, per target or per code size constraints,
perhaps as a configure option.


Thanks,
Corinna



More information about the Newlib mailing list