www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.math.atan2 -- range of output

I've run into an interesting little issue with respect to std.math.atan2.

This is used to calculate the "argument" of complex numbers, that is, the angle 
in polar coordinates.  atan2(y, x) gives the argument of the complex number x +
iy.

Now, theoretically, atan2 ought to return a value in the range (-PI, PI] or [0, 
2 * PI) in order to avoid potential ambiguities in output: an argument of PI or 
-PI is equivalent, and so is one of 0 and 2 * PI.

However, it's possible to get it to return a value of -PI as follows:

     writeln(atan2(0.0, -1.0));   // argument of -1 : it's PI.
     writeln(atan2(-0.0, -1.0));  // still arg of -1, but this time it's -PI.

This can be traced to L863-869 of std/math.d where we have the lines:

     if (y == 0.0)
     {
         if (x >= 0 && !signbit(x))
             return copysign(0, y);
         else
             return copysign(PI, y);
     }

That is to say, y's sign is copied to the returned argument value, so if we 
provide y as -0.0 instead of 0.0, we get -PI instead of PI.

Can someone explain the logic here?  The effect so far as I can see is to
render 
an unpleasant ambiguity for dependent functions like std.complex.arg where it's 
possible for the user to wind up with an out-of-the-blue -PI argument where PI 
was expected.

I ask because I ran into this while trying to create a unittest for the case

     (-1.0) ^^ complex(1.0, 1.0);

... as part of the work I'm doing on
https://d.puremagic.com/issues/show_bug.cgi?id=11652
Nov 30 2013