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

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

GNU awk unable to handle 64-bit ints on IA64


From: Jean-Marc Saffroy
Subject: GNU awk unable to handle 64-bit ints on IA64
Date: Tue, 26 Apr 2005 21:12:49 +0200 (CEST)

Hello,

I have rounding problems when manipulating 64-bit ints (actually they are addresses) on Linux/IA64:

$ echo 0xa000000100000813|./gawk '{printf("0x%lx\n",strtonum($1));}'
0xa000000100000800
$ echo 0xffffffffffffffff|./gawk '{printf("0x%lx\n",strtonum($1));}'
0x8000000000000000
$ ./gawk --version|head -1
GNU Awk 3.1.4

The problem seems to be that AWKNUM is defined to be a double, which has a 53-bit mantissa. On IA64 with gcc 3.2.3 (maybe other compilers as well) there is a long double type with a larger mantissa:

$ grep define.*LDBL_MANT_DIG 
/usr/lib/gcc-lib/ia64-redhat-linux/3.2.3/include/float.h
#define LDBL_MANT_DIG 64

So I changed AWKNUM to be a long double; this does not seem to be sufficient, because of some dubious casts to double (there may be others left, I didn't check), see patch below. Now it's much nicer:

$ echo 0xa000000100000813|./gawk '{printf("0x%lx\n",strtonum($1));}'
0xa000000100000813
$ echo 0xffffffffffffffff|./gawk '{printf("0x%lx\n",strtonum($1));}'
0xffffffffffffffff

Maybe the gawk configure script should set AWKNUM to be a long double on Linux/IA64?


Regards,

--
Jean-Marc Saffroy - address@hidden


diff -ru gawk-3.1.4/awk.h gawk/awk.h
--- gawk-3.1.4/awk.h    2004-07-26 16:11:05.000000000 +0200
+++ gawk/awk.h  2005-04-26 19:19:10.545419273 +0200
@@ -273,7 +273,7 @@
 /* ------------------ Constants, Structures, Typedefs  ------------------ */

 #ifndef AWKNUM
-#define AWKNUM double
+#define AWKNUM long double
 #endif

 #ifndef TRUE
diff -ru gawk-3.1.4/builtin.c gawk/builtin.c
--- gawk-3.1.4/builtin.c        2004-07-13 09:55:28.000000000 +0200
+++ gawk/builtin.c      2005-04-26 20:53:41.211365432 +0200
@@ -578,7 +578,7 @@
        char *cend = &cpbuf[30];/* chars, we lose, but seems unlikely */
        char *cp;
        const char *fill;
-       double tmpval;
+       AWKNUM tmpval;
        char signchar = FALSE;
        size_t len;
        int zero_flag = FALSE;
@@ -2773,16 +2773,16 @@
 do_strtonum(NODE *tree)
 {
        NODE *tmp;
-       double d;
+       AWKNUM d;

        tmp = tree_eval(tree->lnode);

        if ((tmp->flags & (NUMBER|NUMCUR)) != 0)
-               d = (double) force_number(tmp);
+               d = (AWKNUM) force_number(tmp);
        else if (isnondecimal(tmp->stptr))
                d = nondec2awknum(tmp->stptr, tmp->stlen);
        else
-               d = (double) force_number(tmp);
+               d = (AWKNUM) force_number(tmp);

        free_temp(tmp);
        return tmp_number((AWKNUM) d);




reply via email to

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