summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2015-11-28 22:56:29 -0500
committerSteve Hay <steve.m.hay@googlemail.com>2015-11-29 18:26:04 +0000
commit9677f0ce70c0d066e562e5e9f4a2e607f90bc0a7 (patch)
tree1a37fea0a99343971a1268292fc46e59cb499ea3
parent4b0ae52dee99f81c20d3a8d6b59c926e54eb8fa3 (diff)
downloadperl-9677f0ce70c0d066e562e5e9f4a2e607f90bc0a7.tar.gz
hexfp: printf %.13a 0.0
(cherry picked from commit 798a7a50ba821b0294cbf03dc1e274fa128084db)
-rw-r--r--sv.c37
-rw-r--r--t/op/sprintf2.t6
2 files changed, 30 insertions, 13 deletions
diff --git a/sv.c b/sv.c
index 17607e59f8..0a46ebcd5a 100644
--- a/sv.c
+++ b/sv.c
@@ -12298,6 +12298,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
@@ -12305,6 +12306,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.
*
@@ -12353,8 +12355,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) {
@@ -12414,9 +12414,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
@@ -12432,17 +12447,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;
diff --git a/t/op/sprintf2.t b/t/op/sprintf2.t
index 1f0c515d3d..48986f0e06 100644
--- a/t/op/sprintf2.t
+++ b/t/op/sprintf2.t
@@ -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");
}