Re: atan2_sharp() -- a Motion?
On Tue, Feb 25, 2014 at 10:05 AM, Michel Hack <mhack@xxxxxxx> wrote:
> John Pryce wrote:
>> If people have no objection to such a function, let's have a motion.
>
> I was going to propose a simple motion that sort of side-steps the issues,
> namely to suggest adding atan2m() and atan2p() to the list of recommended
> operations in 10.7 (Table 10.6), with Note g referring to a new subsection,
> either 10.7.2 (shifting others) or 10.7.1.1 (insertion only):
>
> 10.7.1.1. atan2_sharp()
>
> One issue with the interval extension of the standard atan2() function,
> with range (-pi,+pi], is that a tight input box that straddles the x axis
> on the negative side would like to return a tight result that includes
> either -pi or +pi. But with the atan2() range this is not possible, and
> atan2() would have to return a maximally-wide result of [-pi,+pi].
>
> By allowing a choice of branch cut, either atan2m() with range (-2pi,0]
> or atan2p() with range [0,+2pi), a programmer can construct a sharp
> version of atan2. (Nevertheless an actual atan2_sharp() function is not
> recommended, because (a) such a function is technically not an interval
> extension of one point function, and (b) there is no generally-useful
> fixed rule for choosing a branch cut based on a given input box.
>
> But then it occurred to me that atan2m() and atan2p() are not the only
> choices. Any rule that selects among two or three fixed branch cuts
> suffers from the problem that, as a tight input box slides across the
> point where the branch cut choice is made, the result jumps by 2pi.
>
> What we want is a branch cut choice where the cross-over point is far
> from the expected result.
>
> So perhaps what we need is atan3(yy,xx,m) where m is an estimate of the
> expected result midpoint (think of it as a parameter rather than as a
> third interval input). The programmer could then implement atan2_sharp()
> by using context information about the expected result, and pick the
> appropriate m for atan2_sharp(yy,xx) = atan3(yy,xx,m). This will pick
> a branch cut such that the range of atan3(yy,xx,m) is (m-pi,m+pi].
>
> Is that reasonable? People who regularly program with branch cuts,
> please chime in, because I don't.
My reaction to the above is that it is more complex than necessary.
After all, the caller of atan2() almost certainly does not care about
the difference between atan2m() and atan2p(). So, from the
perspective of that choice, almost all users would want the
atan2_sharp() function to make that choice internally.
I think the overall question turns on the guarantee to a user that an
implementer provides as dictated by the standard. Classical atan2()
never puts a result outside the half circle centered on the origin.
That has unfortunate effects when crossing the negative X axis.
The alternative cannot avoid encountering a discontinuity at multiples
of the circumference of a unit circle. But those discontinuities can
be tamed in part by selecting selecting an alternative point of
discontinuity. If atan2_pos()'s range is [0,tau] than the
discontinuity occurs at the positive X axis instead of the negative X
axis.
Once we offer an effective way for the users to avoid such artifactual
failures caused by crossing a discontinuity we are done.
Now a user with an input that contains [0,0] (with all discussion of
the interpretation of signed zeros suppressed) is going to have to
deal with a discontinuity on one side or the other of the X axis. So
they probably won't care. But a returned interval whose width exceeds
tau would be, IMNSHO, an implementation defect.
N.B., Naming. An alternative function named atan2_pos() with range
[0,tau] would make sense. That leaves the name atan2_sharp() for the
function that returns the narrowest of atan2() and atan2_pos().
FWIW,
Lee Winter
Nashua, New Hampshire
United States of America