Re: GiNaC-list Digest, Vol 29, Issue 1
Dear Richard, Thanks for the prompt reply. I'm no expert and not aware of LIA-3. Maybe you could give me a reference as where to obtain it? The reason I posted the question is that since GiNaC is embedded in C++ (beautiful concept by the way) it seems odd to have different definitions for the case at hand. Of course I can't oversee the consequences of a change, it would be convenient to code decisions based on the argument in a uniform way though. Best regards Jan Bos On Sun, 2007-07-22 at 12:00 +0200, ginac-list-request@ginac.de wrote:
Send GiNaC-list mailing list submissions to ginac-list@ginac.de
To subscribe or unsubscribe via the World Wide Web, visit https://www.cebix.net/mailman/listinfo/ginac-list or, via email, send a message with subject or body 'help' to ginac-list-request@ginac.de
You can reach the person managing the list at ginac-list-owner@ginac.de
When replying, please edit your Subject line so it is more specific than "Re: Contents of GiNaC-list digest..."
Today's Topics:
1. atan2(0,-4) = -Pi? (Jan Bos) 2. Re: atan2(0,-4) = -Pi? (Richard B. Kreckel)
----------------------------------------------------------------------
Message: 1 Date: Sat, 21 Jul 2007 21:24:57 +0200 From: Jan Bos <jb68@xs4all.nl> Subject: [GiNaC-list] atan2(0,-4) = -Pi? To: ginac-list@ginac.de Message-ID: <1185045897.9600.20.camel@jbos1> Content-Type: text/plain
Dear All,
Is there a reason for GiNaC (or ginsh) to evaluate atan2(0,-4) as -Pi instead of +Pi the definition used by for instance C/C++? Looking at the code, inifcns_trans.cpp last shown case below, explicitly states it should. Or can I expect it to be changed in the future?
static ex atan2_eval(const ex & y, const ex & x) { if (y.info(info_flags::numeric) && x.info(info_flags::numeric)) {
if (y.is_zero()) {
// atan(0, 0) -> 0 if (x.is_zero()) return _ex0;
// atan(0, x), x real and positive -> 0 if (x.info(info_flags::positive)) return _ex0;
// atan(0, x), x real and negative -> -Pi if (x.info(info_flags::negative)) return _ex_1*Pi; }
...
The code fragment is from version 1.3.7
best regards
Jan Bos
------------------------------
Message: 2 Date: Sun, 22 Jul 2007 01:16:38 +0200 From: "Richard B. Kreckel" <kreckel@ginac.de> Subject: Re: [GiNaC-list] atan2(0,-4) = -Pi? To: GiNaC discussion list <ginac-list@ginac.de> Message-ID: <46A293D6.9040301@ginac.de> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Dear Jan,
Jan Bos wrote:
Is there a reason for GiNaC (or ginsh) to evaluate atan2(0,-4) as -Pi instead of +Pi the definition used by for instance C/C++? Looking at the code, inifcns_trans.cpp last shown case below, explicitly states it should. Or can I expect it to be changed in the future?
static ex atan2_eval(const ex & y, const ex & x) { if (y.info(info_flags::numeric) && x.info(info_flags::numeric)) {
if (y.is_zero()) {
// atan(0, 0) -> 0 if (x.is_zero()) return _ex0;
// atan(0, x), x real and positive -> 0 if (x.info(info_flags::positive)) return _ex0;
// atan(0, x), x real and negative -> -Pi if (x.info(info_flags::negative)) return _ex_1*Pi; }
I don't suppose anybody lightly intends to change such definitions. :)
Well, I looked in my notes and didn't find anything motivating that choice for atan2.
I recall that back when I wrote this, CLTL 2nd edition provided guidance when choosing branch cuts of single-argument functions in the complex domain. And later at some point I realized that the C99 standard agrees with CLTL for all single-argument functions. (That appeared to be too good to be true, but it is true.) Nobody was aware of LIA-3 at that time but I'm quite sure that all of GiNaC's single-argument functions agree with LIA-3, simply because they agree with C99.
Our two-argument function atan2, however, may never have been checked against any standard. I just did that with C99 and CLTL, and they both specify atan2(0,-4) to be +Pi, indeed. Maybe, we ought to change this? Before we do so: What does LIA-3 say?
Our choice may be bad but I frankly admit that I don't know why +Pi is any better than -Pi, or a more symmetric choice a la Mathematica like atan2(0,x>0)=Pi/2, atan2(0,x<0)=-Pi/2, or 0 for all x. Can you explain that choice?
Cheers -richy.
PS: In any case, this is a good lesson how not to write comments, sigh. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
------------------------------
_______________________________________________ GiNaC-list mailing list GiNaC-list@ginac.de https://www.cebix.net/mailman/listinfo/ginac-list
End of GiNaC-list Digest, Vol 29, Issue 1 *****************************************
Jan Bos wrote:
Thanks for the prompt reply. I'm no expert and not aware of LIA-3. Maybe you could give me a reference as where to obtain it?
The links in <http://en.wikipedia.org/wiki/ISO/IEC_10967> appear to be as good as it gets regarding downloadable stuff.
The reason I posted the question is that since GiNaC is embedded in C++ (beautiful concept by the way) it seems odd to have different definitions for the case at hand.
Surely, the intent is to avoid such differing definitions.
Of course I can't oversee the consequences of a change, it would be convenient to code decisions based on the argument in a uniform way though.
Let's see. atan2 appears in LIA-2 and LIA-3, though not in LIA-1. It isn't defined directly, but one finds for instance the formula in LIA-3: ln(z)=ln(|z|)+I*atan2(y,x) for z=x+I*y. This implies to bring the branch cut in alignment with the branch cut of ln(x+I*y). The latter is defined as continuous with the second quadrant of the x-y plane (c.f. C99, 7.3.3.2: "[...] implementations shall map a cut so the function is continuous as the cut is approached coming around the finite endpoint of the cut in a counter clockwise direction. (Brnach cuts for the functions specified here have just one finite endpoint.)" As I said, this branch cut specification for ln(z) is consistent with the other standards. IINM this implies that atan2(0,-4) should be +Pi, not -Pi. Unless somebody is going to hold me back I'm going to fix this in GiNaC RSN. I'll also consider some minor other issues like atan2(I*1.1,1.1) throws an exception but atan2(I,1)->atan2(I,1) (both arguments of atan2 must be real, full stop.) -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hi! Richard B. Kreckel wrote:
Of course I can't oversee the consequences of a change, it would be convenient to code decisions based on the argument in a uniform way though.
Let's see. atan2 appears in LIA-2 and LIA-3, though not in LIA-1. It isn't defined directly, but one finds for instance the formula in LIA-3: ln(z)=ln(|z|)+I*atan2(y,x) for z=x+I*y. This implies to bring the branch cut in alignment with the branch cut of ln(x+I*y). The latter is defined as continuous with the second quadrant of the x-y plane (c.f. C99, 7.3.3.2: "[...] implementations shall map a cut so the function is continuous as the cut is approached coming around the finite endpoint of the cut in a counter clockwise direction. (Brnach cuts for the functions specified here have just one finite endpoint.)" As I said, this branch cut specification for ln(z) is consistent with the other standards.
IINM this implies that atan2(0,-4) should be +Pi, not -Pi.
The old definition of atan2(0,-4)==-Pi did not only disagree with C99, it also caused real inconsistencies: ex z = -4; cout << log(z) << endl; // log(4)+I*Pi cout << log(z).imag_part() << endl; // -Pi I've fixed that on both active branches in CVS.
Unless somebody is going to hold me back I'm going to fix this in GiNaC RSN. I'll also consider some minor other issues like atan2(I*1.1,1.1) throws an exception but atan2(I,1)->atan2(I,1) (both arguments of atan2 must be real, full stop.)
Restricting atan2(y,x) to real arguments would be more restrictive than is needed. A suitable analytic continuation of atan2(y,x) to complex arguments y and x can be found in some other systems, too: -I*log((x+I*y)/sqrt(x^2+y^2)). As a result, more values are accepted, now. Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
participants (2)
-
Jan Bos
-
Richard B. Kreckel