Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 4 Apr 2014 16:58:08 -0400
From: Rich Felker <>
Subject: Re: printf issues

On Fri, Apr 04, 2014 at 01:42:30PM -0400, Morten Welinder wrote:
> > I _would_ like this code to be easily adaptable for use outside libc
> > if somebody wants it
> FYI, I have been doing just that for Gnumeric in a variant that always
> rounds ties away from zero.  Two changes would help with making
> the code fit seamlessly into other environments.
> 1. Make "i" in fmt_fp unsigned.  It's used in connection with
>     unsigned values only.

I don't object, but what's the motivation?

> 2. Make "char *s" used to hold "NAN" etc. "const char *s".

Indeed, this is harmless. I assume it's to satisfy that ugly option
that changes the type of string literals from char[] to const char[]?
BTW that option actually just got a lot more problematic with C11; now
that C has _Generic, it potentially changes the semantics of a program
rather than just helping generate warnings.

> Neither of these should make any difference in what the function
> actually does.
> I have run tens of millions random numbers through this function
> looking for differences between it and glibc.  The extra 0s from "%g"
> is the only problem observed.

Nice. I was actually thinking of some numerical tests we could run on
huge random samples, for instance using using theorems about
properties of the digits of the decimal expansion (e.g. n%3==0 iff the
sum of the digits mod 3==0; this works for diadic-rational 'multiples
of 3' too).

> It looks like the LDBL_EPSILON version could be used in
>     roundl.c
>     modfl.c
>     ceill.c
>     floorl.c
> in the definition of TOINT instead of enumerating choices for
> LDBL_MANT_DIG.  It's basically the same thing going on
> there.

Indeed, this would be a welcome change.

> While I was looking for that, I noticed that this modfl fallback looks
> problematic.  Even if long double and double are the same thing
> under the hood, I don't think you can cast pointers like that and
> assume it works.  It needs a temporary.
> #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
> long double modfl(long double x, long double *iptr)
> {
> return modf(x, (double *)iptr);
> }

Agreed. This is UB (an aliasing violation) and should be fixed even if
it makes the function a few bytes larger/a few cycles slower.


Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.