4 quadrant atan

Charles Sanders C.delete_this.Sanders at BoM.GOv.AU
Thu May 3 22:04:58 EDT 2007


Roel Schroeven wrote:
> 
> I might be wrong of course, but can't you just use atan2? Only problem 
> is that it returns negative angles for quadrants 3 and 4, but that is 
> easily solved. In Python:
> 
> from math import atan2, pi, fmod
> def vectorAngle(x, y):
>     return fmod(atan2(y, x) + 2*pi, 2*pi)
> 
> No conditionals in sight.
> 

	Yes, but there will be some conditionals for special
cases in the implementation of atan2().

	I am pretty sure that in Python (and Perl) atan2() is
the C atan2() from the C math library, also often used by
Fortran.

	This is normally written in assembler for the individual
architecture by the hardware vendor or compiler writer, is usually
heavily optimized, carefully handles all the corner cases, and
often carries extra precision to ensure accuracy.

	If I recall correctly P. J. Plauger's book on the C
standard library ("The Standard C Library") includes a C version
of atan2(), which is probably pretty typical of the algorithms
used when there is no hardware support for trigonometric functions.

	As I remember it, atan2 (and atan) in Plauger's book
use a ratio of polynomials to approximate atan(x) over a
limited range, (such as -1.0 ... +1.0 or 0.0 ... sqrt(2)-1)
and formulae (assuming I have remembered high school
trigonometry correctly) such as atan(x) = pi/2 - atan(1/x)
and atan(x) = pi/4 - atan((1-x)/(1+x)) [derived from tan(pi/4-x)
= (1-x)/(1+x)] to extend the range.

	There is an obvious trade off between the complexity
of the approximating polynomials (and the range they cover
with acceptable accuracy), and the number of cases needed to
extend the range to all valid inputs. For example, if the
polynomials cover -1.0 ... +1.0 (atan() values of -pi/4
to +pi/4) then there are at least 5 cases to consider
(atan() ranges -pi ... -3pi/4, -3pi/4 ... -pi/4, -pi/4
... +pi4, +pi/4 ... +3pi/4, +3pi/4 ... +pi), while if the
approximations only cover 0.0 ... sqrt(2)-1 (atan() values
from 0.0 to pi/8) then there are at least 16 cases. NaNs
and infinities would add additional cases, as may the need
to preserve accuracy near zero.


Charles



More information about the Python-list mailing list