diff options
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | interpret.h | 27 | ||||
-rw-r--r-- | node.c | 20 | ||||
-rw-r--r-- | test/ChangeLog | 6 | ||||
-rw-r--r-- | test/Makefile.am | 12 | ||||
-rw-r--r-- | test/Makefile.in | 12 | ||||
-rw-r--r-- | test/mpfrfield.awk | 14 | ||||
-rw-r--r-- | test/mpfrfield.in | 10 | ||||
-rw-r--r-- | test/mpfrfield.ok | 1 |
9 files changed, 102 insertions, 15 deletions
@@ -1,3 +1,18 @@ +2018-04-01 Arnold D. Robbins <arnold@skeeve.com> + + Fix a nasty MPFR bug in r_dupnode. If the value being copied + is MPFN / MPFR, copy those bits over too. Thanks to + Noah Dean <N.Dean@gaminglabs.com> for the report. + + * node.c (r_dupnode): Check for MPFN / MPFR and copy the bits + over as needed. + + Unrelated: + + * interpret.h (UNFIELD): Turn into an inline function and + let UNFIELD macro call it, allows stepping in with a debugger. + (unfield): Function holding former body of UNFIELD macro. + 2018-03-26 Arnold D. Robbins <arnold@skeeve.com> Remove the tail recursion optimization. It's fundamentally diff --git a/interpret.h b/interpret.h index 96e2c890..20fcb7ad 100644 --- a/interpret.h +++ b/interpret.h @@ -32,16 +32,25 @@ * valref 1, that effectively means that this is an assignment like "$n = $n", * so a no-op, other than triggering $0 reconstitution. */ -#define UNFIELD(l, r) \ -{ \ - /* if was a field, turn it into a var */ \ - if ((r->flags & MALLOC) != 0 || r->valref == 1) { \ - l = r; \ - } else { \ - l = dupnode(r); \ - DEREF(r); \ - } \ + +// not a macro so we can step into it with a debugger +#ifndef UNFIELD_DEFINED +#define UNFIELD_DEFINED 1 +static inline void +unfield(NODE **l, NODE **r) +{ + /* if was a field, turn it into a var */ + if (((*r)->flags & MALLOC) != 0 || (*r)->valref == 1) { + (*l) = (*r); + } else { + (*l) = dupnode(*r); + DEREF(*r); + } } + +#define UNFIELD(l, r) unfield(& (l), & (r)) +#endif + int r_interpret(INSTRUCTION *code) { @@ -306,8 +306,24 @@ r_dupnode(NODE *n) } #endif - getnode(r); - *r = *n; +#ifdef HAVE_MPFR + if ((n->flags & MPZN) != 0) { + r = mpg_integer(); + mpz_set(r->mpg_i, n->mpg_i); + r->flags = n->flags; + } else if ((n->flags & MPFN) != 0) { + r = mpg_float(); + int tval = mpfr_set(r->mpg_numbr, n->mpg_numbr, ROUND_MODE); + IEEE_FMT(r->mpg_numbr, tval); + r->flags = n->flags; + } else { +#endif + getnode(r); + *r = *n; +#ifdef HAVE_MPFR + } +#endif + r->flags |= MALLOC; r->valref = 1; /* diff --git a/test/ChangeLog b/test/ChangeLog index e075e3ac..5f806e11 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,9 @@ +2018-04-01 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (EXTRA_DIST): Add files for mpfrfield. + (MPFR_TESTS): Add mpfrfield. + * mpfrfield.awk, mpfrfield.awk, mpfrfield.ok: New files. + 2018-03-26 Arnold D. Robbins <arnold@skeeve.com> * fwtest3.in, mmap8k.awk, mmap8k.ok, rsstart2.in: New files. diff --git a/test/Makefile.am b/test/Makefile.am index bfb0c4b3..fe4fd816 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -658,6 +658,9 @@ EXTRA_DIST = \ mpfrbigint.ok \ mpfrexprange.awk \ mpfrexprange.ok \ + mpfrfield.awk \ + mpfrfield.in \ + mpfrfield.ok \ mpfrieee.awk \ mpfrieee.ok \ mpfrmemok1.awk \ @@ -1307,8 +1310,8 @@ INET_TESTS = inetdayu inetdayt inetechu inetecht MACHINE_TESTS = double1 double2 fmtspcl intformat -MPFR_TESTS = mpfrbigint mpfrexprange mpfrieee mpfrmemok1 mpfrnegzero \ - mpfrnr mpfrrem mpfrrnd mpfrrndeval mpfrsort mpfrsqrt \ +MPFR_TESTS = mpfrbigint mpfrexprange mpfrfield mpfrieee mpfrmemok1 \ + mpfrnegzero mpfrnr mpfrrem mpfrrnd mpfrrndeval mpfrsort mpfrsqrt \ mpfrstrtonum mpgforcenum mpfruplus LOCALE_CHARSET_TESTS = \ @@ -2140,6 +2143,11 @@ mpfrmemok1: @$(AWK) -p- -M -f "$(srcdir)"/$@.awk 2>&1 | sed 1d > _$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +mpfrfield: + @echo $@ + @$(AWK) -M -f "$(srcdir)"/$@.awk "$(srcdir)"/$@.in > _$@ 2>&1 + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + jarebug:: @echo $@ @"$(srcdir)"/$@.sh "$(AWKPROG)" "$(srcdir)"/$@.awk "$(srcdir)"/$@.in "_$@" diff --git a/test/Makefile.in b/test/Makefile.in index 1f2ff766..33e2b0bf 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -916,6 +916,9 @@ EXTRA_DIST = \ mpfrbigint.ok \ mpfrexprange.awk \ mpfrexprange.ok \ + mpfrfield.awk \ + mpfrfield.in \ + mpfrfield.ok \ mpfrieee.awk \ mpfrieee.ok \ mpfrmemok1.awk \ @@ -1560,8 +1563,8 @@ ARRAYDEBUG_TESTS = arrdbg EXTRA_TESTS = inftest regtest ignrcas3 INET_TESTS = inetdayu inetdayt inetechu inetecht MACHINE_TESTS = double1 double2 fmtspcl intformat -MPFR_TESTS = mpfrbigint mpfrexprange mpfrieee mpfrmemok1 mpfrnegzero \ - mpfrnr mpfrrem mpfrrnd mpfrrndeval mpfrsort mpfrsqrt \ +MPFR_TESTS = mpfrbigint mpfrexprange mpfrfield mpfrieee mpfrmemok1 \ + mpfrnegzero mpfrnr mpfrrem mpfrrnd mpfrrndeval mpfrsort mpfrsqrt \ mpfrstrtonum mpgforcenum mpfruplus LOCALE_CHARSET_TESTS = \ @@ -2580,6 +2583,11 @@ mpfrmemok1: @$(AWK) -p- -M -f "$(srcdir)"/$@.awk 2>&1 | sed 1d > _$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +mpfrfield: + @echo $@ + @$(AWK) -M -f "$(srcdir)"/$@.awk "$(srcdir)"/$@.in > _$@ 2>&1 + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + jarebug:: @echo $@ @"$(srcdir)"/$@.sh "$(AWKPROG)" "$(srcdir)"/$@.awk "$(srcdir)"/$@.in "_$@" diff --git a/test/mpfrfield.awk b/test/mpfrfield.awk new file mode 100644 index 00000000..35a97b70 --- /dev/null +++ b/test/mpfrfield.awk @@ -0,0 +1,14 @@ +#! /bin/gawk -Mf + +NR == 1 { + min = $1 +} + +{ + if ($1 < min) + min = $1 +} + +END { + print "min", min +} diff --git a/test/mpfrfield.in b/test/mpfrfield.in new file mode 100644 index 00000000..05d33444 --- /dev/null +++ b/test/mpfrfield.in @@ -0,0 +1,10 @@ +7 +9 +1 +3 +9 +1 +9 +5 +0 +8 diff --git a/test/mpfrfield.ok b/test/mpfrfield.ok new file mode 100644 index 00000000..3736de4d --- /dev/null +++ b/test/mpfrfield.ok @@ -0,0 +1 @@ +min 0 |