On Sat, 27 Dec 2008 21:24:10 +0100 Roland Mainz wrote:
> This is basically a spin-off of
> http://bugs.opensolaris.org/view_bug.do?bug_id=6773712 ("1-digit hex fp
> base conversion of long double rounds incorrectly").
> The bug description for Solaris libc says this:
> > The first line of output from this program is correct.  The second line
> > is not.
> > 
> > leviathan% cat a.c
> > #include <stdio.h>
> > 
> > int main()
> > {
> >     printf("%.0a\n", 1.5);
> >     printf("%.0La\n", 1.5L);
> >     return 0;
> > }
> > leviathan% cc -o a a.c
> > leviathan% a
> > 0x1p+1
> > 0x1p+0
> > leviathan%

an 'aA' format rounding patch for src/lib/libast/sfio/sfcvt.c follows

but I have a question about the leading hex digit 0 or 1 (0x1*)
what is the source of this requirement
posix and c99 only state:

    where there is one hexadecimal digit (which is nonzero if
    the argument is a normalized floating-point number and is
    otherwise unspecified) before the decimal-point character

the libast/sfio implementation also formats to the 0x1* form
but gnu libc does not

--- .../sfio/sfcvt.c    Tue Aug 19 03:32:17 2008
+++ sfio/sfcvt.c        Sun Dec 28 04:41:52 2008
@@ -210,7 +210,9 @@
                                while ((x -= 4) >= 0)
                                {       *sp++ = ep[(m >> x) & 0xf];
                                        if (sp >= endsp)
-                                       {       ep = sp + 1;
+                                       {       if (((m >> x) & 0xf) >= 8)
+                                                       (*decpt)++;
+                                               ep = sp + 1;
                                                goto done;
                                        }
                                }
@@ -369,13 +371,13 @@
                        return SF_INF;
 
                if(format & SFFMT_AFORMAT)
-               {       double  g;
-                       int     x;
+               {       double          g;
+                       int             x;
                        b = sp = buf;
                        ep = (format & SFFMT_UPPER) ? ux : lx;
                        if(n_digit <= 0 || n_digit >= (size - 9))
                                n_digit = size - 9;
-                       endsp = sp + n_digit;
+                       endsp = sp + n_digit + 1;
 
                        g = frexp(f, &x);
                        *decpt = x;
@@ -387,7 +389,9 @@
                                while ((x -= 4) >= 0)
                                {       *sp++ = ep[(m >> x) & 0xf];
                                        if (sp >= endsp)
-                                       {       ep = sp + 1;
+                                       {       if (((m >> x) & 0xf) >= 8)
+                                                       (*decpt)++;
+                                               ep = sp + 1;
                                                goto done;
                                        }
                                }


Reply via email to