bug-gawk
[Top][All Lists]
Advanced

[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 */



reply via email to

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