[Top][All Lists]
[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);
- GNU awk unable to handle 64-bit ints on IA64,
Jean-Marc Saffroy <=