atan versus atan2

⇐ 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]$.

  1. 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.