[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bug-gawk] Overflow to Infinity
From: |
Arnold Robbins |
Subject: |
Re: [bug-gawk] Overflow to Infinity |
Date: |
Fri, 06 Jul 2018 10:28:57 +0300 |
User-agent: |
Heirloom mailx 12.5 6/20/10 |
Greetings all.
> From: address@hidden
> Date: Sun, 24 Jun 2018 00:09:09 -0600
> To: address@hidden, address@hidden
> Subject: Re: [bug-gawk] Overflow to Infinity
> Cc: address@hidden, address@hidden
>
> [ Other stuff, including Arnold being needlessly snarky at Andy, deleted. ]
>
> Issue #2 is that gawk can print "inf", which means it can output stuff
> that it can't read back later:
>
> $ gawk 'BEGIN { print 2+2, -log(0) }'
> 4 inf
>
> It is this latter issue that I am choosing to not deal with at the moment.
I have finally dealt with it. This is the patch I'd like to
push shortly.
Andy - if you have a few minutes, please review. I think it solves the
output problem. (Grrrr. I forgot to update the doc. Darn!!!)
(Double Grrrr. I need to deal with MPFR values for this case, too.)
There remains an issue of numeric comparisons, with NaN values in
particular, that produce incorrect results. I have started looking
at the code and thinking about this, but the various flows for comparison
within gawk are somewhat twisty and confusing. It's an area that's
a little bit fragile, and is complicated by the fact that it has
to be fixed for both regular floating-point values and for MPFR values.
Thanks,
Arnold
---------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 947e46d..a6191a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2018-07-06 Arnold D. Robbins <address@hidden>
+
+ * builtin.c (format_nan_inf): New function to generate +nan, -nan,
+ +inf, -inf, so that gawk output for NaN and INF always has a sign.
+ (format_tree): Use it in out of range calculation. Check for out
+ of range in floating point formats also.
+
2018-06-27 Arnold D. Robbins <address@hidden>
* config.guess, config.sub: Updated from GNULIB.
diff --git a/builtin.c b/builtin.c
index c54be9b..fe5bf1b 100644
--- a/builtin.c
+++ b/builtin.c
@@ -66,6 +66,7 @@
static size_t mbc_byte_count(const char *ptr, size_t numchars);
static size_t mbc_char_count(const char *ptr, size_t numbytes);
+static char *format_nan_inf(double val);
/* Can declare these, since we always use the random shipped with gawk */
extern char *initstate(unsigned long seed, char *state, long n);
@@ -722,6 +723,7 @@ format_tree(
int ii, jj;
char *chp;
size_t copy_count, char_count;
+ char *nan_inf_val;
#ifdef HAVE_MPFR
mpz_ptr zi;
mpfr_ptr mf;
@@ -820,6 +822,7 @@ format_tree(
signchar = '\0';
zero_flag = false;
quote_flag = false;
+ nan_inf_val = NULL;
#ifdef HAVE_MPFR
mf = NULL;
zi = NULL;
@@ -1476,12 +1479,22 @@ mpf1:
break;
out_of_range:
- /* out of range - emergency use of %g format */
+ /*
+ * out of range - emergency use of %g format,
+ * or format NaN and INF values.
+ */
if (do_lint)
lintwarn(_("[s]printf: value %g is out of range
for `%%%c' format"),
(double) tmpval, cs1);
- cs1 = 'g';
- goto fmt1;
+ nan_inf_val = format_nan_inf(tmpval);
+ if (do_posix || nan_inf_val == NULL) {
+ cs1 = 'g';
+ goto fmt1;
+ } else {
+ bchunk(nan_inf_val, strlen(nan_inf_val));
+ s0 = s1;
+ break;
+ }
case 'F':
#if ! defined(PRINTF_HAS_F_FORMAT) || PRINTF_HAS_F_FORMAT != 1
@@ -1508,8 +1521,11 @@ mpf1:
parse_next_arg();
(void) force_number(arg);
- if (! is_mpg_number(arg))
+ if (! is_mpg_number(arg)) {
tmpval = arg->numbr;
+ if (isnan(tmpval) || isinf(tmpval))
+ goto out_of_range;
+ }
#ifdef HAVE_MPFR
else if (is_mpg_float(arg)) {
mf = arg->mpg_numbr;
@@ -4204,3 +4220,24 @@ int sanitize_exit_status(int status)
return ret;
}
+
+/* format_nan_inf --- format NaN and INF values */
+
+static char *
+format_nan_inf(double val)
+{
+ static char buf[100];
+
+ if (isnan(val)) {
+ sprintf(buf, "%g", val);
+ if (strcmp(buf, "nan") == 0) // "-nan" or "nan"
+ strcpy(buf, "+nan");
+
+ return buf;
+ } else if (isinf(val)) {
+ strcpy(buf, val < 0 ? "-inf" : "+inf");
+
+ return buf;
+ } else
+ return NULL;
+}
diff --git a/test/ChangeLog b/test/ChangeLog
index 0b41abb..c3492be 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,8 @@
+2018-07-06 Arnold D. Robbins <address@hidden>
+
+ * fmtspcl.awk: Revised after code changes.
+ * numrange.ok: Ditto.
+
2018-06-22 Andrew J. Schorr <address@hidden>
* Makefile.am (EXTRA_DIST): Add files for numrange.
diff --git a/test/fmtspcl.awk b/test/fmtspcl.awk
index 6f037a3..7a15379 100644
--- a/test/fmtspcl.awk
+++ b/test/fmtspcl.awk
@@ -12,6 +12,7 @@ BEGIN {
nnan_str = sprintf("%f",-nan)
inf = -log(0)
inf_str = sprintf("%f",inf)
+ ninf_str = sprintf("%f",-inf)
n = 0
formats[n++] = "%f"
@@ -22,5 +23,5 @@ BEGIN {
display(nan,nan_str)
display(-nan,nnan_str)
display(inf,inf)
- display(-inf,"-"inf_str)
+ display(-inf,ninf_str)
}
diff --git a/test/numrange.ok b/test/numrange.ok
index 006da13..73210bd 100644
--- a/test/numrange.ok
+++ b/test/numrange.ok
@@ -1,2 +1,2 @@
-1.2e+931 -inf
-1.2e+931 inf
+1.2e+931 +inf