bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gawk: use long double for AWKNUM when useful


From: Jean-Marc Saffroy
Subject: gawk: use long double for AWKNUM when useful
Date: Thu, 29 Apr 2010 01:24:11 +0200 (CEST)

Hi (again),

In a previous life, I had suggested that defining AWKNUM as long double on 
IA64 would be beneficial:

http://lists.gnu.org/archive/html/bug-gnu-utils/2005-04/msg00094.html

Recently I saw that gawk had only partial support for this. The patch 
below uses AC_TYPE_LONG_DOUBLE_WIDER to test when long double is useful. 
It also enables longdbl in the test suite, and adds a macro for a length 
modifier to printf when required.

It is worth noting that HAVE_LONG_DOUBLE_WIDER == 1 on both x86 and 
x86-64, so this may impact performance a bit; but I assume the benefit of 
handling larger integral values is more important (to me it is).

The configury stuff that has to be regenerated is not included (I don't 
have the exact same versions as in the archive). Patch is against 3.1.7.


Cheers,
Jean-Marc

-- 
address@hidden

diff --git a/array.c b/array.c
--- a/array.c
+++ b/array.c
@@ -776,7 +776,7 @@ static void
 pr_node(NODE *n)
 {
        if ((n->flags & (NUMCUR|NUMBER)) != 0)
-               printf("%g", n->numbr);
+               printf("%"NMOD"g", n->numbr);
        else
                printf("%.*s", (int) n->stlen, n->stptr);
 }
diff --git a/awk.h b/awk.h
--- a/awk.h
+++ b/awk.h
@@ -308,17 +308,18 @@ extern double gawk_strtod();
 
 /* ------------------ Constants, Structures, Typedefs  ------------------ */
 
-#if 0
-/* This isn't right. Figure it out the right way for the next release */
 #ifndef AWKNUM
-#ifdef LDBL_MANT_DIG
+#ifdef HAVE_LONG_DOUBLE_WIDER
 #define AWKNUM long double
+#define NMOD "L"               /* length modifier for printf */
 #else
-#endif
+#define AWKNUM double
 #endif
 #endif
 
-#define AWKNUM double
+#ifndef NMOD
+#define NMOD ""                        /* length modifier for printf */
+#endif
 
 #ifndef TRUE
 /* a bit hackneyed, but what the heck */
@@ -1011,7 +1012,7 @@ extern int check_special P((const char *
 extern void register_deferred_variable P((const char *name,
                                          NODE *(*load_func)(void)));
 /* builtin.c */
-extern double double_to_int P((double d));
+extern AWKNUM double_to_int P((AWKNUM d));
 extern NODE *do_exp P((NODE *tree));
 extern NODE *do_fflush P((NODE *tree));
 extern NODE *do_index P((NODE *tree));
diff --git a/awkgram.y b/awkgram.y
--- a/awkgram.y
+++ b/awkgram.y
@@ -2717,13 +2717,13 @@ valinfo(NODE *n, FILE *fp)
                pp_string_fp(fp, n->stptr, n->stlen, '"', FALSE);
                fprintf(fp, ")\n");
        } else if (n->flags & NUMBER)
-               fprintf(fp, "number (%.17g)\n", n->numbr);
+               fprintf(fp, "number (%.17"NMOD"g)\n", n->numbr);
        else if (n->flags & STRCUR) {
                fprintf(fp, "string value (");
                pp_string_fp(fp, n->stptr, n->stlen, '"', FALSE);
                fprintf(fp, ")\n");
        } else if (n->flags & NUMCUR)
-               fprintf(fp, "number value (%.17g)\n", n->numbr);
+               fprintf(fp, "number value (%.17"NMOD"g)\n", n->numbr);
        else
                fprintf(fp, "?? flags %s\n", flags2str(n->flags));
 }
diff --git a/builtin.c b/builtin.c
--- a/builtin.c
+++ b/builtin.c
@@ -411,8 +411,8 @@ out:
 
 /* double_to_int --- convert double to int, used several places */
 
-double
-double_to_int(double d)
+AWKNUM
+double_to_int(AWKNUM d)
 {
        if (d >= 0)
                d = Floor(d);
@@ -978,7 +978,7 @@ check_pos:
                                uval = (uintmax_t) arg->numbr;
 #endif
                                if (do_lint && uval > 255) {
-                                       lintwarn("[s]printf: value %g is too 
big for %%c format",
+                                       lintwarn("[s]printf: value %"NMOD"g is 
too big for %%c format",
                                                        arg->numbr);
                                }
                                cpbuf[0] = uval;
@@ -1044,7 +1044,7 @@ check_pos:
                         * is enough room in the buffer or not.
                         */
                        while ((i = snprintf(cpbufs[1].buf,
-                                            cpbufs[1].bufsize, "%.0f",
+                                            cpbufs[1].bufsize, "%.0"NMOD"f",
                                             tmpval)) >=
                               cpbufs[1].bufsize) {
                                if (cpbufs[1].buf == cpbufs[1].stackbuf)
@@ -2840,11 +2840,11 @@ do_lshift(NODE *tree)
        shift = force_number(s2);
        if (do_lint) {
                if (val < 0 || shift < 0)
-                       lintwarn(_("lshift(%lf, %lf): negative values will give 
strange results"), val, shift);
+                       lintwarn(_("lshift(%"NMOD"f, %"NMOD"f): negative values 
will give strange results"), val, shift);
                if (double_to_int(val) != val || double_to_int(shift) != shift)
-                       lintwarn(_("lshift(%lf, %lf): fractional values will be 
truncated"), val, shift);
+                       lintwarn(_("lshift(%"NMOD"f, %"NMOD"f): fractional 
values will be truncated"), val, shift);
                if (shift >= sizeof(uintmax_t) * CHAR_BIT)
-                       lintwarn(_("lshift(%lf, %lf): too large shift value 
will give strange results"), val, shift);
+                       lintwarn(_("lshift(%"NMOD"f, %"NMOD"f): too large shift 
value will give strange results"), val, shift);
        }
 
        free_temp(s1);
@@ -2878,11 +2878,11 @@ do_rshift(NODE *tree)
        shift = force_number(s2);
        if (do_lint) {
                if (val < 0 || shift < 0)
-                       lintwarn(_("rshift(%lf, %lf): negative values will give 
strange results"), val, shift);
+                       lintwarn(_("rshift(%"NMOD"f, %"NMOD"f): negative values 
will give strange results"), val, shift);
                if (double_to_int(val) != val || double_to_int(shift) != shift)
-                       lintwarn(_("rshift(%lf, %lf): fractional values will be 
truncated"), val, shift);
+                       lintwarn(_("rshift(%"NMOD"f, %"NMOD"f): fractional 
values will be truncated"), val, shift);
                if (shift >= sizeof(uintmax_t) * CHAR_BIT)
-                       lintwarn(_("rshift(%lf, %lf): too large shift value 
will give strange results"), val, shift);
+                       lintwarn(_("rshift(%"NMOD"f, %"NMOD"f): too large shift 
value will give strange results"), val, shift);
        }
 
        free_temp(s1);
@@ -2916,9 +2916,9 @@ do_and(NODE *tree)
        right = force_number(s2);
        if (do_lint) {
                if (left < 0 || right < 0)
-                       lintwarn(_("and(%lf, %lf): negative values will give 
strange results"), left, right);
+                       lintwarn(_("and(%"NMOD"f, %"NMOD"f): negative values 
will give strange results"), left, right);
                if (double_to_int(left) != left || double_to_int(right) != 
right)
-                       lintwarn(_("and(%lf, %lf): fractional values will be 
truncated"), left, right);
+                       lintwarn(_("and(%"NMOD"f, %"NMOD"f): fractional values 
will be truncated"), left, right);
        }
 
        free_temp(s1);
@@ -2952,9 +2952,9 @@ do_or(NODE *tree)
        right = force_number(s2);
        if (do_lint) {
                if (left < 0 || right < 0)
-                       lintwarn(_("or(%lf, %lf): negative values will give 
strange results"), left, right);
+                       lintwarn(_("or(%"NMOD"f, %"NMOD"f): negative values 
will give strange results"), left, right);
                if (double_to_int(left) != left || double_to_int(right) != 
right)
-                       lintwarn(_("or(%lf, %lf): fractional values will be 
truncated"), left, right);
+                       lintwarn(_("or(%"NMOD"f, %"NMOD"f): fractional values 
will be truncated"), left, right);
        }
 
        free_temp(s1);
@@ -2988,9 +2988,9 @@ do_xor(NODE *tree)
        right = force_number(s2);
        if (do_lint) {
                if (left < 0 || right < 0)
-                       lintwarn(_("xor(%lf, %lf): negative values will give 
strange results"), left, right);
+                       lintwarn(_("xor(%"NMOD"f, %"NMOD"f): negative values 
will give strange results"), left, right);
                if (double_to_int(left) != left || double_to_int(right) != 
right)
-                       lintwarn(_("xor(%lf, %lf): fractional values will be 
truncated"), left, right);
+                       lintwarn(_("xor(%"NMOD"f, %"NMOD"f): fractional values 
will be truncated"), left, right);
        }
 
        free_temp(s1);
@@ -3009,7 +3009,7 @@ NODE *
 do_compl(NODE *tree)
 {
        NODE *tmp;
-       double d;
+       AWKNUM d;
        uintmax_t uval;
 
        tmp = tree_eval(tree->lnode);
@@ -3020,9 +3020,9 @@ do_compl(NODE *tree)
 
        if (do_lint) {
                if (d < 0)
-                       lintwarn(_("compl(%lf): negative value will give 
strange results"), d);
+                       lintwarn(_("compl(%"NMOD"f): negative value will give 
strange results"), d);
                if (double_to_int(d) != d)
-                       lintwarn(_("compl(%lf): fractional value will be 
truncated"), d);
+                       lintwarn(_("compl(%"NMOD"f): fractional value will be 
truncated"), d);
        }
 
        uval = (uintmax_t) d;
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -198,6 +198,7 @@ gl_AC_TYPE_LONG_LONG
 gl_AC_TYPE_UNSIGNED_LONG_LONG
 gl_AC_TYPE_INTMAX_T
 gl_AC_TYPE_UINTMAX_T
+AC_TYPE_LONG_DOUBLE_WIDER
 AC_CHECK_TYPE(ssize_t, int)
 AC_CHECK_SIZEOF(unsigned int)
 AC_CHECK_SIZEOF(unsigned long)
diff --git a/floatcomp.c b/floatcomp.c
--- a/floatcomp.c
+++ b/floatcomp.c
@@ -79,6 +79,9 @@ Please port the following code to your w
 AWKNUM
 Floor(AWKNUM n)
 {
+#ifdef HAVE_LONG_DOUBLE_WIDER
+       return floorl(n);
+#else
        return floor(n
 #if 0
 #ifdef _CRAY
@@ -86,6 +89,7 @@ Floor(AWKNUM n)
 #endif
 #endif
        );
+#endif
 }
 
 /* Ceil --- do ceil(), also for Cray */
@@ -93,6 +97,9 @@ Floor(AWKNUM n)
 AWKNUM
 Ceil(AWKNUM n)
 {
+#ifdef HAVE_LONG_DOUBLE_WIDER
+       return ceill(n);
+#else
        return ceil(n
 #if 0
 #ifdef _CRAY
@@ -100,6 +107,7 @@ Ceil(AWKNUM n)
 #endif
 #endif
        );
+#endif
 }
 
 #ifdef HAVE_UINTMAX_T
diff --git a/profile.c b/profile.c
--- a/profile.c
+++ b/profile.c
@@ -456,7 +456,7 @@ tree_eval(register NODE *tree)
 
        case Node_val:
                if ((tree->flags & NUMBER) != 0)
-                       fprintf(prof_fp, "%g", tree->numbr);
+                       fprintf(prof_fp, "%"NMOD"g", tree->numbr);
                else {
                        if ((tree->flags & INTLSTR) != 0)
                                fprintf(prof_fp, "_");
diff --git a/test/Makefile.am b/test/Makefile.am
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -675,8 +675,6 @@ EXTRA_DIST = \
        zeroflag.awk \
        zeroflag.ok
 
-TESTS_WE_ARE_NOT_DOING_YET_FIXME_ONE_DAY = longdbl
-
 # Get rid of core files when cleaning and generated .ok file
 CLEANFILES = core core.* fmtspcl.ok
 
@@ -722,7 +720,7 @@ EXTRA_TESTS = regtest inftest
 
 INET_TESTS = inetechu inetecht inetdayu inetdayt
 
-MACHINE_TESTS = double1 double2 fmtspcl intformat
+MACHINE_TESTS = double1 double2 fmtspcl intformat longdbl
 
 LOCALE_CHARSET_TESTS = asort asorti fmttest fnarydel fnparydl lc_num1 mbfw1 \
        mbprintf1 mbprintf2 rebt8b2 sort1 sprintfc whiny




reply via email to

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