This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
hexfp: printf %.13a 0.0
authorJarkko Hietaniemi <jhi@iki.fi>
Sun, 29 Nov 2015 03:56:29 +0000 (22:56 -0500)
committerJarkko Hietaniemi <jhi@iki.fi>
Sun, 29 Nov 2015 14:52:00 +0000 (09:52 -0500)
sv.c
t/op/sprintf2.t

diff --git a/sv.c b/sv.c
index d080f1f..79b8a50 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -12332,6 +12332,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                 U8* v = vhex; /* working pointer to vhex */
                 U8* vend; /* pointer to one beyond last digit of vhex */
                 U8* vfnz = NULL; /* first non-zero */
+                U8* vlnz = NULL; /* last non-zero */
                 const bool lower = (c == 'a');
                 /* At output the values of vhex (up to vend) will
                  * be mapped through the xdig to get the actual
@@ -12339,6 +12340,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                 const char* xdig = PL_hexdigit;
                 int zerotail = 0; /* how many extra zeros to append */
                 int exponent = 0; /* exponent of the floating point input */
+                bool hexradix = FALSE; /* should we output the radix */
 
                 /* XXX: denormals, NaN, Inf.
                  *
@@ -12387,8 +12389,6 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                 }
 
                 if (vfnz) {
-                    U8* vlnz = NULL; /* The last non-zero. */
-
                     /* Find the last non-zero xdigit. */
                     for (v = vend - 1; v >= vhex; v--) {
                         if (*v) {
@@ -12448,9 +12448,24 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                     v = vhex;
                     *p++ = xdig[*v++];
 
-                    /* The radix is always output after the first
-                     * non-zero xdigit, or if precis, or if alt.  */
-                    if (vfnz < vlnz || precis > 0 || alt) {
+                    /* If there are non-zero xdigits, the radix
+                     * is output after the first one. */
+                    if (vfnz < vlnz) {
+                      hexradix = TRUE;
+                    }
+                }
+                else {
+                    *p++ = '0';
+                    exponent = 0;
+                    zerotail = precis;
+                }
+
+                /* The radix is always output if precis, or if alt. */
+                if (precis > 0 || alt) {
+                  hexradix = TRUE;
+                }
+
+                if (hexradix) {
 #ifndef USE_LOCALE_NUMERIC
                         *p++ = '.';
 #else
@@ -12466,17 +12481,17 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
                         }
                         RESTORE_LC_NUMERIC();
 #endif
-                    }
+                }
 
+                if (vlnz) {
                     while (v <= vlnz)
                         *p++ = xdig[*v++];
-
-                    while (zerotail--)
-                        *p++ = '0';
                 }
-                else {
+
+                if (zerotail > 0) {
+                  while (zerotail--) {
                     *p++ = '0';
-                    exponent = 0;
+                  }
                 }
 
                 elen = p - PL_efloatbuf;
index 1f0c515..48986f0 100644 (file)
@@ -69,6 +69,7 @@ if ($Config{nvsize} == 8 &&
 
         [ '%.13a',    '1',   '0x1.0000000000000p+0' ],
         [ '%.13a',    '-1',  '-0x1.0000000000000p+0' ],
+        [ '%.13a',    '0',   '0x0.0000000000000p+0' ],
 
         [ '%30a',  '3.14',   '          0x1.91eb851eb851fp+1' ],
         [ '%-30a', '3.14',   '0x1.91eb851eb851fp+1          ' ],
@@ -246,7 +247,7 @@ if ($Config{nvsize} == 8 &&
     print "# no hexfloat tests\n";
 }
 
-plan tests => 1408 + ($Q ? 0 : 12) + @hexfloat + 8;
+plan tests => 1408 + ($Q ? 0 : 12) + @hexfloat + 9;
 
 use strict;
 use Config;
@@ -682,8 +683,9 @@ SKIP: {
 }
 
 SKIP: {
-    skip("negative zero not available\n", 2)
+    skip("negative zero not available\n", 3)
         unless sprintf('%+f', -0.0) =~ /^-0/;
     is(sprintf("%a", -0.0), "-0x0p+0", "negative zero");
     is(sprintf("%+a", -0.0), "-0x0p+0", "negative zero");
+    is(sprintf("%.13a", -0.0), "-0x0.0000000000000p+0", "negative zero");
 }