[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bug-gawk] atan2(y,x) return value for y = 0 and x = -0
From: |
Aharon Robbins |
Subject: |
Re: [bug-gawk] atan2(y,x) return value for y = 0 and x = -0 |
Date: |
Sun, 19 Jan 2014 21:16:22 +0200 |
User-agent: |
Heirloom mailx 12.5 6/20/10 |
Hello.
> Date: Sat, 18 Jan 2014 14:56:19 +0100
> From: Hermann Peifer <address@hidden>
> To: address@hidden
> Cc: address@hidden
> Subject: [bug-gawk] atan2(y,x) return value for y = 0 and x = -0
>
> Hi,
>
> This might be a feature or a bug, but I thought it would be worth reporting.
>
> # Works as expected
> $ awk 'BEGIN{ pi = atan2(0,-0) ; printf "%.16f\n", pi }'
> 3.1415926535897931
>
> # Why is the result 0 here ?
> $ awk -M 'BEGIN{ pi = atan2(0,-0) ; printf "%.16f\n", pi }'
> 0.0000000000000000
>
> # Works again as expected
> $ awk -M 'BEGIN{ pi = atan2(0,-0.1) ; printf "%.16f\n", pi }'
> 3.1415926535897931
>
> # I used gawk from git on Mac OS X, 10.9.1
> $ awk -V | head -1
> GNU Awk 4.1.60, API: 1.0 (GNU MPFR 3.1.1-p2, GNU MP 5.1.2)
>
> Hermann
This is a bug. Internally, when -M is used, gawk distinguishes between
multiprecision integers and multiprecision floating point.
-0.0 gets correctly handled, but for -0 the fact that it was negative got
lost; apparently, multiprecision integers, just like hardware integers,
don't distinguish negative zero from positive zero.
The fix is below. I will be pushing it out to the git repo shortly.
Thanks,
Arnold
-------------------------------------------------------------
diff --git a/awkgram.y b/awkgram.y
index 5846c13..fd83d6d 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -1964,16 +1964,33 @@ getfname(NODE *(*fptr)(int))
void
negate_num(NODE *n)
{
+ int tval = 0;
+
+ if (! is_mpg_number(n))
+ n->numbr = -n->numbr;
#ifdef HAVE_MPFR
- if (is_mpg_float(n)) {
- int tval;
- tval = mpfr_neg(n->mpg_numbr, n->mpg_numbr, ROUND_MODE);
+ else if (is_mpg_integer(n)) {
+ if (! iszero(n)) {
+ mpz_neg(n->mpg_i, n->mpg_i);
+ return;
+ }
+
+ /*
+ * 0 --> -0 conversion. Requires turning the MPG integer
+ * into an MPFR float.
+ *
+ * So, convert and fall through.
+ */
+ tval = mpfr_set_d(n->mpg_numbr, 0.0, ROUND_MODE);
IEEE_FMT(n->mpg_numbr, tval);
- } else if (is_mpg_integer(n)) {
- mpz_neg(n->mpg_i, n->mpg_i);
- } else
+ n->flags &= ~MPZN;
+ n->flags |= MPFN;
+ }
+
+ /* mpfr float case */
+ tval = mpfr_neg(n->mpg_numbr, n->mpg_numbr, ROUND_MODE);
+ IEEE_FMT(n->mpg_numbr, tval);
#endif
- n->numbr = -n->numbr;
}
/* print_included_from --- print `Included from ..' file names and locations */