aboutsummaryrefslogtreecommitdiffstats
path: root/node.c
diff options
context:
space:
mode:
authorjohn haque <j.eh@mchsi.com>2012-03-19 04:30:00 -0500
committerjohn haque <j.eh@mchsi.com>2012-03-19 04:30:00 -0500
commit40645cb3cb155eb59dd745af4ae0e06e729c8eb1 (patch)
tree1c24a9a6cb2ac9acc985b3f4667c7139c10c4525 /node.c
parentb5431a4825e325c61f4043e4d25e47d7891c228c (diff)
downloadegawk-40645cb3cb155eb59dd745af4ae0e06e729c8eb1.tar.gz
egawk-40645cb3cb155eb59dd745af4ae0e06e729c8eb1.tar.bz2
egawk-40645cb3cb155eb59dd745af4ae0e06e729c8eb1.zip
Add arbitrary-precision arithmetic on integers.
Diffstat (limited to 'node.c')
-rw-r--r--node.c37
1 files changed, 34 insertions, 3 deletions
diff --git a/node.c b/node.c
index 27ed791b..8dbe68a9 100644
--- a/node.c
+++ b/node.c
@@ -26,14 +26,17 @@
#include "awk.h"
#include "math.h"
+#include "floatmagic.h" /* definition of isnan */
static int is_ieee_magic_val(const char *val);
+static NODE *r_make_number(double x);
static AWKNUM get_ieee_magic_val(const char *val);
extern NODE **fmt_list; /* declared in eval.c */
NODE *(*make_number)(double) = r_make_number;
NODE *(*str2number)(NODE *) = r_force_number;
NODE *(*format_val)(const char *, int, NODE *) = r_format_val;
+int (*cmp_numbers)(const NODE *, const NODE *) = cmp_awknums;
/* force_number --- force a value to be numeric */
@@ -321,9 +324,9 @@ r_dupnode(NODE *n)
return r;
}
-/* make_number --- allocate a node with defined number */
+/* r_make_number --- allocate a node with defined number */
-NODE *
+static NODE *
r_make_number(double x)
{
NODE *r;
@@ -341,6 +344,32 @@ r_make_number(double x)
return r;
}
+/* cmp_awknums --- compare two AWKNUMs */
+
+int
+cmp_awknums(const NODE *t1, const NODE *t2)
+{
+ /*
+ * This routine is also used to sort numeric array indices or values.
+ * For the purposes of sorting, NaN is considered greater than
+ * any other value, and all NaN values are considered equivalent and equal.
+ * This isn't in compliance with IEEE standard, but compliance w.r.t. NaN
+ * comparison at the awk level is a different issue, and needs to be dealt
+ * with in the interpreter for each opcode seperately.
+ */
+
+ if (isnan(t1->numbr))
+ return ! isnan(t2->numbr);
+ if (isnan(t2->numbr))
+ return -1;
+ /* don't subtract, in case one or both are infinite */
+ if (t1->numbr == t2->numbr)
+ return 0;
+ if (t1->numbr < t2->numbr)
+ return -1;
+ return 1;
+}
+
/* r_make_str_node --- make a string node */
@@ -443,8 +472,10 @@ r_unref(NODE *tmp)
#endif
#ifdef HAVE_MPFR
- if ((tmp->flags & MPFN) != 0)
+ if (is_mpg_float(tmp))
mpfr_clear(tmp->mpg_numbr);
+ else if (is_mpg_integer(tmp))
+ mpz_clear(tmp->mpg_i);
#endif
free_wstr(tmp);