Sun Jan 26 04:09:36 2014, comment #21:
Thanks for taking a look. Closing this report as fixed.

Sun Jan 26 02:54:55 2014, comment #20:
I think that this was resolved a long time ago.
Good to close this report.

Fri Jan 24 22:48:36 2014, comment #19:
I have no idea anymore about what was going on with this report. Sorry.
Rik

Fri Jan 24 22:10:42 2014, comment #18:
This bug history looks like it has gone through several iterations. It's labeled as documentation but the most recent comments seem to be talking about changing behavior of the atan2 function. Michael or Rik, can one of you refresh your memories on what was left to work on for this bug? Focus it on improving atan2 mapper function? Documentation issues are all resolved? If there were other related issues let's open separate reports to keep things straight.

Fri Sep 28 23:53:11 2012, comment #17:
I looked at lomappers.cc. It appears that
something like what is below would be a start,
but a serious numerical C++ person should take a look.
This should go somewhere after line 249 in lomappers.cc:
i.e., after: // (complex, complex) > complex mappers.
Complex
atan2 (const Complex& x, const Complex& y)
{
return 2 * atan((sqrt (x)^2 + (y)^2  (x) ) / (y) );
}
=====================================
This does not handle the exceptions and quadrants
as far as I can tell, but it may be a start.
Uniformity would definitely be enhanced if atan2 can
be integrated with the other trig functions in
lomappers.cc.

Fri Sep 28 20:49:38 2012, comment #16:
It should probably be in C++. The atan2 function is defined in libinterp/interpfcn/data.cc beginning at line 213. It doesn't look like it would be difficult to translate your mfile code to C++ in this instance.
There is another possibility as well which is that atan2 could be shifted to a mapper function. The mapper functions are in liboctave/numeric/lomappers.[ch]. If you look in lomappers.h you will see that there is a prototype declaration for each function, like asin, that might accept a complex value. lomappers.cc then has a tiny function to implement it. I would ask jwe on the maintainers list about this strategy, though, before going forward.

Fri Sep 28 20:34:50 2012, comment #15:
Well, the code did not apparently make it into
the comment below. In Any case, this code only
handles the exceptions for scalar inputs.
function res = atan2(y, x)
% Test for special cases and quadrants.
if(x == 0)
if(y > 0)
res = pi/2;
elseif (y < 0)
res = pi/2;
else
res = NaN;
endif
return;
endif
res = atan(y/x);
if(x < 0)
if(y >= 0)
res = res + pi;
else
res = res  pi;
endif
endif
return;
endfunction

Fri Sep 28 19:07:42 2012, comment #14:
Below is a try at making atan2 more compatible
with the other trig functions, which allow complex
arguments. This needs more checking, and maybe
it should really be in C?

Fri Sep 28 02:07:48 2012, comment #13:
I have looked at this a bit more. The single
argument trig and inverse trig functions appear
to follow Kahan for complex arguments. This
differs from (extends) the ISO/IEC definitions
for reals (with + 0). However, atan2 does not
do this. Thus, for complex arguments
atan2(y,x) != atan(y/x) despite the help doc which
says that it is. atan2 does not accept complex
arguments.
Maybe atan2(y,x) should correctly preserve the
signs of y and x and use atan?
I will look more at how Maple does this.

Wed Sep 26 17:23:44 2012, comment #12:
That makes sense to me. After a bit of thought,
I will add this behaviour to the documentation.

Wed Sep 26 17:02:49 2012, comment #11:
I don't think we need to adhere to the GNU spec. In particular, I think it would be better to follow what mathematicians do and if they extend the range of the function with branch cuts or whatever then we can too. To my simple mind, the acos() and cos() functions are inverses and that is the property I expect to hold at all times. The domain of the function is a secondary concern to me.
In this case, the inverse property is maintained even though the domain has been extended.

Wed Sep 26 16:00:15 2012, comment #10:
We are not consistent. We use M_PI in several places, but it is defined only in liboctave/numeric/lospecfun.cc:50. So it would appear that some places, say quadcc.cc, may be using another definition. Of course, maybe it is being defined in a system header file. I was only grepping in the Octave tree. See the attached file for a list of occurrences.
(file #26645)

Wed Sep 26 15:35:00 2012, comment #9:
The GNU libc doc says:
The math library normally defines M_PI to a double approximation of pi. If strict ISO and/or POSIX compliance are requested this constant is not defined, but you can easily define it yourself:
#define M_PI 3.14159265358979323846264338327
==========================
Do we do this?
Also, the GNU doc says:
The arc cosine function is defined mathematically only over the domain 1 to 1. If x is outside the domain, acos signals a domain error.
And similar for other inverse functions. Octave currently does not return an error. Instead it returns a complex result.
This is also Matlab behaviour. Should we adhere to the GNU
spec?

Wed Sep 26 15:24:49 2012, comment #8:
Rik,
Thanks! I was just doing a build.
I have some more to add, including what
I can find out about the differences between
libm and the ISO/EDC spec.

Wed Sep 26 15:10:46 2012, comment #7:
I pushed a changeset (http://hg.savannah.gnu.org/hgweb/octave/rev/46dd555edd33) for a malformed @tex construct that was stopping the documentation build. You'll want to do an 'hg pull; hg update' before continuing with the patch.

Wed Sep 26 14:17:34 2012, comment #6:
Well, OK. I had not even compiled it.
But, if you could push the attached minor
update,then I will do the rest as one
more final patch.
Thanks
(file #26644)

Wed Sep 26 12:44:03 2012, comment #5:
I have pushed your patch:
http://hg.savannah.gnu.org/hgweb/octave/rev/0b6c29cb53d0
It looks like useful information to me. Thanks. I am marking this bug "in progress" since it looks like you want to keep working on it.

Wed Sep 26 01:59:10 2012, comment #4:
Attached is a first draft of updates to the
trig functions doc.
I need to add indexing terms, and it would be
good to have more crossreferences...
Comments?
(file #26638)

Tue Sep 25 21:46:08 2012, comment #3:
Oops, 2 typos:
— atan2(y, ±0) returns pi/2 for y < 0. both pi/2 *
— atan2(y, ±0) returns pi/2 for y > 0. both pi/2 *
should be:
— atan2(y, ±0) returns pi/2 for y < 0. both pi/2
— atan2(y, ±0) returns pi/2 for y > 0. both pi/2
It appears that Matlab does not recognize 0.
Someone might check this with newer Matlabs.

Tue Sep 25 21:37:08 2012, comment #2:
matlab r2009b differs from Octave and ISO/IEC as follows:
(* in the right hand column means Matlab differs)
F.9.1.4 The atan2 functions Matlab r2009B Differs from Octave
— atan2(±0, 0) returns ±pi. both 0 *
— atan2(±0, +0) returns ±0. both 0 *
— atan2(±0, x) returns ±pi for x < 0. + pi
— atan2(±0, x) returns ±0 for x > 0. both 0 *
— atan2(y, ±0) returns pi/2 for y < 0. both pi/2 *
— atan2(y, ±0) returns pi/2 for y > 0. both pi/2 *
— atan2(±y, Inf) returns ±pi for finite y > 0. + pi
— atan2(±y, +Inf) returns ±0 for finite y > 0.
both 0 *
— atan2(±Inf, x) returns ±pi/2 for finite x. + pi/2
— atan2(±Inf, Inf) returns ±3pi/4. + 3pi/4
— atan2(±Inf, +Inf) returns ±pi/4. + pi/4
Octave adhers to ISO/IEC. By far the most serious Matlab
issue is atan2(±0, 0)
I will work on documentation patch for this and other trig
functions.

Sun Sep 23 18:09:36 2012, comment #1:
There was a huge discussion about atan2 and how to handle float values on the mailing list some years back. It seems that Apple has a different interpretation of the ISO C standards than everyone else.
But for doubles, the situation is clearer. Octave picks up the C atan2 function and the underlying C library should be C99 compliant. In that case, Octave's behavior is defined by the ISO/IEC 9899 standard. First, that means that atan2 is defined over the range [pi,pi] inclusive. Second, the behavior of special values is mandated in section Annex F.9.1.4. I'll quote them for ease. I don't know if it is worth documenting them all inside Octave or whether you want to write a patch that refers to the ISO standard.
F.9.1.4 The atan2 functions
— atan2(±0, 0) returns ±pi.
— atan2(±0, +0) returns ±0.
— atan2(±0, x) returns ±pi for x < 0.
— atan2(±0, x) returns ±0 for x > 0.
— atan2(y, ±0) returns pi/2 for y < 0.
— atan2(y, ±0) returns pi/2 for y > 0.
— atan2(±y, Inf) returns ±pi for finite y > 0.
— atan2(±y, +Inf) returns ±0 for finite y > 0.
— atan2(±Inf, x) returns ±pi/2 for finite x.
— atan2(±Inf, Inf) returns ±3pi/4.
— atan2(±Inf, +Inf) returns ±pi/4.

Tue Sep 18 00:56:24 2012, original submission:
I have been using atan2(y,x) and finally found a problem that I
might have guessed at sooner. But on checking the documentation
I found that there is practically none.
It appears that the atan2 function that is used is compliant with
some standards. But, a few of the cases that caused me
trouble were not included anywhere that I could find. I was not
aware that: atan2(0, 0) => pi for example.
So, some checking and documentation is in order.
The attached file shows what I found. If anyone knows of
better documentation that would be great. Otherwise the Wikipedia
page plus some additions from the attached file may work
Comments?
