bug-gawk
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]