atan versus atan2
01 Mar 2021 ⇐ Notes archive(This is an entry in my technical notebook. There will likely be typos, mistakes, or wider logical leaps — the intent here is to “let others look over my shoulder while I figure things out.”)
I never really thought twice — let alone since high school pre-calculus — about the atan
function (shorthand for arctangent)1. And it wasn’t until Richard Borcherds pointed out the difference between atan
and atan2
(the arity two form) in a recent complex analysis lecture, that I realized I also haven’t paused with why there’s two variants.
The two-argument form is needed because the single-argument function loses the individual signs (positive or negative) of triangle side lengths whereas atan2
keeps them in tact. Why is this important? Well, if we swing out $\frac{\pi}{4}$ along the unit circle in the anti-clockwise direction (with unit side lengths of the triangle formed) or diametrically by $-\frac{3\pi}{4}$ (with negative unit triangle side lengths), atan
will give the same answer for both $\frac{y}{x}$ ratios — whoops. Here’s that subtle gotcha in Swift with a CoreGraphics
import.
import CoreGraphics
atan(CGFloat(-1) / -1) == atan(CGFloat(1) / 1) // ⇒ true
atan(CGFloat(1) / 1) == .pi / 4 // ⇒ true
atan2
resolves this collision by separating out the lone $\frac{y}{x}$ CGFloat
passed to atan
into two arguments in $y$-first-then-$x$ order.
// Along the unit circle, anti-clockwise (positive radian direction).
atan2(CGFloat(1), 1) == .pi / 4 // ⇒ true
atan2(CGFloat(1), -1) == 3 * .pi / 4 // ⇒ true
atan2(CGFloat(0), -1) == .pi // ⇒ true
// Along the unit circle, clockwise (negative radian direction).
atan2(CGFloat(-1), 1) == -.pi / 4 // ⇒ true
atan2(CGFloat(-1), -1) == -3 * .pi / 4 // ⇒ true
Moreover, TIL the phrasing around resolving collisions from integer multiples of $2\pi$ being added to any angle without changing the resulting $x$ or $y$: “restricting to principal values.”
atan
is restricted to $\left(-\frac{\pi}{2}, \frac{\pi}{2}\right)$ principal values — to account for the domain spanning from $\left(\texttt{-CGFloat.infinity}, \texttt{.infinity}\right)$ — and atan2
to the range $\left(-\pi, \pi\right]$.
-
Looked into the etymology of the “arc” prefix while writing this — it’s from the fact that, in radians, the inverse trigonometric functions return angle values that correspond to the arc lengths they trace along the unit circle (!). Arturo Magidin put this well in their Mathematics Stack Exchange answer:
When measuring in radians, an angle of $\theta$ radians will correspond to an arc whose length is $r\theta$, where $r$ is the radius of the circle.
Thus, in the unit circle, “the arc whose cosine is $x$” is the same as “the angle whose cosine is $x$,” because the measurement of the length of the arc of the circle is the same as the measurement of the angle in radians.