Computing the angle of a 2D vector is one of the most common operations in graphics, robotics, and signal processing: heading angles, joint angles, phase of a complex signal, and orientation of a screen-space vector all boil down to turning a pair \((x,y)\) into an angle. The function that does this correctly, across all four quadrants and without dividing by zero, is \(\operatorname{atan2}(y,x)\). A general-purpose library implementation of it is comparatively expensive: it has to branch on the quadrant, guard against \(x=0\), and evaluate a transcendental function to near machine precision. When this call happens millions of times per frame or per sample, trading a fraction of a degree of accuracy for a handful of multiplications is often a very good deal. This chapter derives \(\operatorname{atan2}\) from \(\arctan\) from first principles, builds up several families of fast approximations mathematically, and turns each one directly into working code as a consequence of its formula.
Defining atan2
For \(\arctan\), the principal value is restricted to \(\left(-\frac{\pi}{2},\frac{\pi}{2}\right)\), which is not enough to describe a full turn. \(\operatorname{atan2}(y,x)\) removes this restriction by looking at the signs of \(x\) and \(y\) directly, returning the angle of the point \((x,y)\) measured from the positive \(x\)-axis, in \((-\pi,\pi]\):
\[ \operatorname{atan2}(y,x)= \begin{cases} \arctan\!\left(\dfrac{y}{x}\right), & x>0,\\[4pt] \arctan\!\left(\dfrac{y}{x}\right)+\pi, & x<0,\ y\ge 0,\\[4pt] \arctan\!\left(\dfrac{y}{x}\right)-\pi, & x<0,\ y<0,\\[4pt] \dfrac{\pi}{2}, & x=0,\ y>0,\\[4pt] -\dfrac{\pi}{2}, & x=0,\ y<0,\\[4pt] 0\ (\text{by convention}), & x=0,\ y=0. \end{cases} \]
Equivalently, \(\operatorname{atan2}(y,x)\) is the argument of the complex number \(x+iy\). Every fast approximation below is really an approximation of \(\arctan\) on a bounded interval, combined with a case analysis that reassembles the full range from it.
Reducing atan2 to a Bounded Domain
Two Identities for the Arctangent
Two identities make it possible to evaluate \(\arctan\) on a small interval and still recover its value everywhere else. The first comes directly from the tangent subtraction formula. For \(\theta=\arctan(t)\) with \(t\in\mathbb{R}\), so that \(\theta\in\left(-\frac{\pi}{2},\frac{\pi}{2}\right)\) and \(\tan\theta=t\):
\[ \tan\!\left(\frac{\pi}{4}-\theta\right)=\frac{1-\tan\theta}{1+\tan\theta}=\frac{1-t}{1+t}. \]
For \(t\ge 0\), the angle \(\frac{\pi}{4}-\theta\) stays inside \(\left(-\frac{\pi}{4},\frac{\pi}{2}\right)\), safely within the principal branch of \(\arctan\), so this can be inverted directly:
\[ \arctan(t)=\frac{\pi}{4}-\arctan\!\left(\frac{1-t}{1+t}\right),\qquad t\ge 0. \]
The right-hand side's argument \(\frac{1-t}{1+t}\) always lies in \((-1,1]\) — no matter how large \(t\) is — which is exactly the reduction needed: any non-negative ratio can be turned into a bounded one.
The second identity is the reciprocal relation. Differentiating \(\arctan(z)+\arctan(1/z)\) with respect to \(z\) gives
\[ \frac{d}{dz}\Big[\arctan(z)+\arctan(1/z)\Big]=\frac{1}{1+z^2}+\frac{-1/z^2}{1+1/z^2}=\frac{1}{1+z^2}-\frac{1}{z^2+1}=0, \]
so the sum is constant on \(z>0\) and on \(z<0\) separately. Evaluating at \(z=1\) gives \(\frac{\pi}{4}+\frac{\pi}{4}=\frac{\pi}{2}\), hence
\[ \arctan(z)+\arctan(1/z)=\operatorname{sign}(z)\cdot\frac{\pi}{2},\qquad z\ne 0. \]
This gives a second way to fold a large ratio back into \([-1,1]\): replace \(z\) by \(1/z\) and subtract from \(\frac{\pi}{2}\).
Two Reduction Strategies
Both identities lead to a working \(\operatorname{atan2}\), and both reappear directly in the code derived further below.
- Direct ratio. Compute \(z=y/x\). If \(|z|\le 1\), approximate \(\arctan(z)\) directly. If \(|z|>1\), use the reciprocal identity to evaluate the approximation at \(1/z\) instead.
- Quadrant ratio. For \(x>0\), set \(t=|y|/x\ge 0\) and \(r=\dfrac{1-t}{1+t}=\dfrac{x-|y|}{x+|y|}\). Since \(r\in(-1,1]\) automatically for every \(t\ge 0\), this needs no separate large-ratio branch at all.
Reassembling the sign and quadrant is the same case analysis either way. For the quadrant-ratio form with \(x>0\):
\[ \operatorname{atan2}(y,x)=\operatorname{sign}(y)\left[\frac{\pi}{4}-\arctan(r)\right],\qquad r=\frac{x-|y|}{x+|y|}. \]
For \(x<0\), reflecting across the \(y\)-axis (\(\operatorname{atan2}(y,-x)=\pi-\operatorname{atan2}(y,x)\) up to the sign convention above) leads to the same formula shifted by \(\frac{\pi}{2}\):
\[ \operatorname{atan2}(y,x)=\operatorname{sign}(y)\left[\frac{3\pi}{4}-\arctan(r)\right],\qquad r=\frac{|x|-|y|}{|x|+|y|}=\frac{-x-|y|}{-x+|y|},\qquad x<0. \]
As a check: for \(x=-1,y=1\), \(r=\frac{-1-1}{-1+1}\) is degenerate, so use the equivalent \(r=\frac{x+|y|}{|y|-x}=\frac{-1+1}{1+1}=0\), giving \(\operatorname{atan2}(1,-1)=\frac{3\pi}{4}-\arctan(0)=\frac{3\pi}{4}\), the correct value.
Approximating Arctan on a Bounded Interval
What remains is approximating \(\arctan\) on \([-1,1]\) cheaply. A Taylor expansion around \(0\) is a poor choice here: it is only accurate near the expansion point, and the number of terms needed to keep the error small over the whole interval grows quickly. Matching a low-degree polynomial or rational function to the endpoints — or minimizing the worst-case error directly (a minimax approximation) — gives far better accuracy per operation.
Linear Approximation
The simplest choice is the line through the two known values \(\arctan(0)=0\) and \(\arctan(1)=\frac{\pi}{4}\):
\[ \arctan(x)\approx\frac{\pi}{4}x,\qquad -1\le x\le 1. \]
Its error \(e(x)=\arctan(x)-\frac{\pi}{4}x\) is an odd function vanishing at \(x=0\) and \(x=\pm 1\). Its extremum satisfies \(e'(x)=\frac{1}{1+x^2}-\frac{\pi}{4}=0\), so
\[ x_{\max}=\pm\sqrt{\frac{4}{\pi}-1}\approx\pm 0.52272. \]
Evaluating at this point gives \(e(x_{\max})\approx 0.0711\) radians, i.e. about \(4.1°\) — the linear approximation is cheap (one multiplication) but coarse.
A Global Rational Approximation
Instead of restricting to \([-1,1]\), the form \(g(z)=\dfrac{\pi}{2}\cdot\dfrac{z}{1+|z|}\) is built to match \(\arctan\) at \(z=0\), at \(z=\pm 1\) (where \(g(\pm1)=\pm\frac{\pi}{4}\)), and asymptotically as \(z\to\pm\infty\) (where \(g\to\pm\frac{\pi}{2}\)), all in a single formula with no branch for large \(|z|\). Its error \(h(z)=\arctan(z)-g(z)\) has \(h'(z)=\dfrac{1}{1+z^2}-\dfrac{\pi/2}{(1+z)^2}\) for \(z\ge0\); setting this to zero and simplifying gives
\[ \left(\frac{\pi}{2}-1\right)z^2-2z+\left(\frac{\pi}{2}-1\right)=0, \]
with reciprocal roots \(z\approx 0.3134\) and \(z\approx 3.1904\) (their product is exactly \(1\), consistent with the \(z\leftrightarrow 1/z\) symmetry of the problem). Evaluating \(h\) at \(z\approx0.3134\) gives \(|h|\approx 0.0712\) radians — essentially the same worst-case accuracy as the plain linear approximation above, reached with a division instead of a branch.
Endpoint-Matched Rational Correction
A better use of a division is the rational form \(\dfrac{z}{1+cz^2}\), restricted to \(|z|\le1\). Matching its Taylor series \(z-cz^3+c^2z^5-\dots\) to \(\arctan(z)=z-\frac{z^3}{3}+\frac{z^5}{5}-\dots\) at the origin favors \(c=\frac13\approx0.333\). Matching the endpoint \(\arctan(1)=\frac{\pi}{4}\) exactly instead gives
\[ \frac{1}{1+c}=\frac{\pi}{4}\quad\Longrightarrow\quad c=\frac{4}{\pi}-1\approx 0.2732. \]
Numerical minimax optimization over the whole interval — rather than matching either the origin or the endpoint alone — nudges the constant to about \(c\approx0.28\), a compromise between the Taylor-accurate \(\frac13\) and the endpoint-accurate \(\frac{4}{\pi}-1\). With \(c\approx0.28\) the worst-case error drops to roughly \(0.005\) radians (\(\approx0.3°\)), and this is the constant used below.
The same rational form combines naturally with the reciprocal identity derived earlier: substituting \(1/z\) for \(z\) gives
\[ \arctan(1/z)\approx\frac{1/z}{1+c/z^2}=\frac{z}{z^2+c}, \]
so \(\arctan(z)\approx\frac{\pi}{2}-\dfrac{z}{z^2+c}\) for \(z>1\) — the same core rational expression, evaluated on the reciprocal argument instead of introducing a second formula.
A Quadratic Correction to the Linear Approximation
Rather than replacing the linear approximation, its error can be corrected directly. The error function \(e(x)=\arctan(x)-\frac{\pi}{4}x\) is odd and vanishes at \(x=0\) and \(x=1\), so \(\alpha\, x(1-x)\) is a natural shape to add back in for \(x\in[0,1]\) (extended by oddness to \(x(1-|x|)\) for negative \(x\)). Fitting a quadratic through the three points \((0,0)\), \((x_{\max},e(x_{\max}))\), and \((1,0)\) via Lagrange interpolation collapses to a single term, since the outer two nodes contribute nothing:
\[ \alpha=\frac{e(x_{\max})}{x_{\max}(1-x_{\max})}=\frac{0.0711}{0.52272\times 0.47728}\approx 0.285, \]
giving
\[ \arctan(x)\approx\frac{\pi}{4}x+0.285\,x(1-|x|),\qquad -1\le x\le 1, \]
which is already close to the endpoint-matching constant \(\frac{4}{\pi}-1\) found for the rational form above. Minimax optimization over the whole interval (rather than matching just these three points) tightens \(\alpha\) further to \(\alpha\approx0.273\approx\frac{4}{\pi}-1\) — the two derivations converge on essentially the same number — pushing the worst-case error down to about \(0.0038\) radians (\(\approx0.22°\)).
A Cubic-Refined Quadrant-Ratio Approximation
The same idea can be applied directly to \(\arctan(r)\) in the quadrant-ratio reduction, using an odd cubic \(\arctan(r)\approx a\,r-b\,r^3\) instead of just \(a\,r\). Matching the exact endpoint \(\arctan(1)=\frac{\pi}{4}\) requires \(a-b=\frac{\pi}{4}\), and one pair of constants found by minimax tuning is
\[ a\approx 0.9817,\qquad b\approx0.1963,\qquad a-b=0.7854\approx\frac{\pi}{4}\ \checkmark \]
which brings the worst-case error for the full \(\operatorname{atan2}\) down to about \(0.01\) radians (\(\approx0.57°\)) — better than the plain linear quadrant-ratio formula, using one extra multiplication.
Assembling Fast atan2 Implementations
Each combination of reduction strategy (direct ratio or quadrant ratio) with an arctangent approximation (diamond, rational, linear-corrected, or cubic-corrected) turns directly into a few lines of code. What follows is exactly that: the formulas derived above, implemented.
The Diamond Approximation
The crudest option skips approximating \(\arctan\) altogether and uses \(g(z)=\frac{\pi}{2}\cdot\frac{z}{1+|z|}\) from above directly, computed via \(p=y/(|x|+|y|)\) (the level sets of \(|x|+|y|\) are diamonds, hence the name). For \(x\ge0\) this is exactly \(g(y/x)\) after dividing through by \(x\); for \(x<0\) the same value is folded across the vertical axis. Its accuracy is what was derived above, about \(4°\) in the worst case:
#include <math.h>
/* error avg: 6.2982%
* error max: 57.0723%
* the accuracy is about 4 degrees */
float diamond_atan2(float y, float x) {
float ax = fabsf(x);
float ay = fabsf(y);
float p = y / (ax + ay);
if (x < 0.0f) {
p = (y < 0.0f ? -2.0f : 2.0f) - p;
}
/* multiply by half of PI */
return p * 1.5707963267948966f;
} The two error figures in the comment measure different things: the absolute error is bounded by about \(4°\) everywhere, but the relative error explodes near \(\theta=0\), where the true angle itself is tiny and even a small absolute error becomes a large fraction of it — hence the much larger reported maximum of \(57\%\).
Direct-Ratio Rational Approximation
Using the direct ratio \(z=y/x\) together with the endpoint-matched rational approximation and its reciprocal counterpart gives an implementation with no unbounded branch and only one division plus a couple of multiplications:
#include <math.h>
#define FAST_ATAN2_PI 3.14159265358979323846f
#define FAST_ATAN2_HALF_PI 1.57079632679489661923f
/* error avg: 0.2217%
* error max: 0.8586%
* the accuracy is about 0.3 degrees */
float fast_atan2(float y, float x) {
float atan_val, z;
if (x == 0.0f) {
if (y == 0.0f) return 0.0f;
return y > 0.0f ? FAST_ATAN2_HALF_PI : -FAST_ATAN2_HALF_PI;
}
z = y / x;
if (z < -1.0f || z > 1.0f) {
atan_val = FAST_ATAN2_HALF_PI - z / (z * z + 0.28f);
if (y < 0.0f) return atan_val - FAST_ATAN2_PI;
} else {
atan_val = z / (1.0f + 0.28f * z * z);
if (x < 0.0f) {
if (y < 0.0f) return atan_val - FAST_ATAN2_PI;
return atan_val + FAST_ATAN2_PI;
}
}
return atan_val;
} Both branches use exactly the rational core \(\frac{z}{1+0.28z^2}\) derived above — the \(|z|>1\) branch is its reciprocal-identity counterpart \(\frac{\pi}{2}-\frac{z}{z^2+0.28}\), matching the code line for line.
Quadrant-Ratio Linear Approximation
Using the quadrant ratio \(r=(x-|y|)/(x+|y|)\) instead avoids the large-ratio branch entirely, at the cost of needing a case for \(x<0\) as well as \(x\ge0\). Since \(r\) divides by \(x+|y|\), which is exactly zero at the origin, a tiny constant is added to \(|y|\) purely to keep that division well-defined; it is negligible everywhere else:
#include <math.h>
#define FAST_ATAN2_QUARTER_PI 0.78539816339744830962f
/* error avg: 6.3354%
* error max: 57.0902%
* the accuracy is about 4 degrees */
float atan2_quadrant_linear(float y, float x) {
float coeff1 = FAST_ATAN2_QUARTER_PI;
float coeff2 = 3.0f * coeff1;
float abs_y = fabsf(y) + 1e-10f; /* avoid 0/0 at the origin */
float r, angle;
if (x >= 0.0f) {
r = (x - abs_y) / (x + abs_y);
angle = coeff1 - coeff1 * r;
} else {
r = (x + abs_y) / (abs_y - x);
angle = coeff2 - coeff1 * r;
}
return y < 0.0f ? -angle : angle;
} This is precisely \(\operatorname{sign}(y)\left[\frac{\pi}{4}-\frac{\pi}{4}r\right]\) for \(x\ge0\) and \(\operatorname{sign}(y)\left[\frac{3\pi}{4}-\frac{\pi}{4}r\right]\) for \(x<0\), the linear-in-\(r\) case derived above.
Quadrant-Ratio Cubic-Refined Approximation
Replacing the linear-in-\(r\) term with the cubic correction derived above (\(a\approx0.9817\), \(b\approx0.1963\)) improves the worst-case accuracy from about \(4°\) down to about \(0.6°\) for one extra multiplication:
#include <math.h>
#define FAST_ATAN2_QUARTER_PI 0.78539816339744830962f
float atan2_quadrant_cubic(float y, float x) {
const float a = 0.9817f, b = 0.1963f;
float abs_y = fabsf(y) + 1e-10f; /* avoid 0/0 at the origin */
float r, angle;
if (x < 0.0f) {
r = (x + abs_y) / (abs_y - x);
angle = 3.0f * FAST_ATAN2_QUARTER_PI;
} else {
r = (x - abs_y) / (x + abs_y);
angle = FAST_ATAN2_QUARTER_PI;
}
angle += (b * r * r - a) * r;
return y < 0.0f ? -angle : angle;
} The line angle += (b * r * r - a) * r is exactly \(-\left(0.9817\,r-0.1963\,r^3\right)\) added to the base constant \(\frac{\pi}{4}\) or \(\frac{3\pi}{4}\) — the cubic quadrant-ratio approximation derived above, ready to use.
Comparing the Approximations
The plot below shows \(\arctan(z)\) together with the plain linear approximation \(\frac{\pi}{4}z\) and the endpoint-matched rational approximation \(\frac{z}{1+cz^2}\) with \(c=\frac{4}{\pi}-1\), extended past \(|z|=1\) via the reciprocal identity. The rational curve tracks \(\arctan\) noticeably closer, especially away from the origin.
| Approximation | Core formula | Max. absolute error | Extra cost vs. linear |
|---|---|---|---|
| Diamond (\(g(z)\)) | \(\frac{\pi}{2}\cdot\frac{z}{1+|z|}\) | \(\approx 4.1°\) | none (no branch on \(|z|>1\)) |
| Linear | \(\frac{\pi}{4}z\) | \(\approx 4.1°\) | — |
| Quadratic-corrected (Lagrange) | \(\frac{\pi}{4}z+0.285\,z(1-|z|)\) | \(\approx0.3°\) | 2 multiplications |
| Quadratic-corrected (minimax) | \(\frac{\pi}{4}z+0.273\,z(1-|z|)\) | \(\approx0.22°\) | 2 multiplications |
| Rational (minimax) | \(\frac{z}{1+0.28z^2}\) | \(\approx0.3°\) | 1 division, 1 multiplication |
| Cubic quadrant-ratio | \(0.9817\,r-0.1963\,r^3\) | \(\approx0.57°\) | 1 multiplication |
An Iterative Alternative: CORDIC
Every approximation above assumes a multiplier is available and spends it on a division or a couple of multiplications for extra accuracy. CORDIC (COordinate Rotation DIgital Computer) takes the opposite route: it computes \(\operatorname{atan2}\) using nothing but additions and power-of-two scalings, which are plain bit shifts in fixed-point arithmetic [Volder59]. That made it the only practical option on hardware without a multiplier at all, such as early calculators, and it remains attractive today on FPGAs and other targets where an adder is far cheaper than a multiplier.
Pseudo-Rotations
Rotating a vector \((x_i,y_i)\) by an angle \(\theta_i\) exactly requires a sine and a cosine:
\[ x'=x_i\cos\theta_i-y_i\sin\theta_i,\qquad y'=x_i\sin\theta_i+y_i\cos\theta_i. \]
Dividing both equations by \(\cos\theta_i\) turns the sine into a tangent:
\[ \frac{x'}{\cos\theta_i}=x_i-y_i\tan\theta_i,\qquad \frac{y'}{\cos\theta_i}=y_i+x_i\tan\theta_i. \]
Restricting \(\theta_i\) to \(\theta_i=d_i\arctan(2^{-i})\) with \(d_i=\pm1\) makes \(\tan\theta_i=d_i\,2^{-i}\) exactly, and the right-hand sides turn into a genuine rotation computed with nothing but an addition and a power-of-two scaling — a bit shift, in fixed-point arithmetic:
\[ x_{i+1}=x_i-d_i\,y_i\,2^{-i},\qquad y_{i+1}=y_i+d_i\,x_i\,2^{-i}. \]
Dropping the \(\cos\theta_i\) factor also stretches the vector by \(1/\cos\theta_i=\sqrt{1+2^{-2i}}\) at every step. This gain depends only on \(i\), never on the data or on \(d_i\), so after a fixed number of iterations it settles on a fixed constant \(K=\prod_i\cos\theta_i\approx0.607253\) that would need correcting for if the final vector length were wanted — but it plays no role at all in the angle, which is exactly what \(\operatorname{atan2}\) needs.
Vectoring Mode: Steering y to Zero
Each pseudo-rotation above is a genuine rotation by \(\theta_i\); applying enough of them in the right directions drives \(y_i\) to \(0\), at which point the accumulated angle equals \(\arg(x,y)\). Rotating a vector currently above the \(x\)-axis clockwise (\(\theta_i<0\)) reduces its angle, and rotating one below the axis counterclockwise (\(\theta_i>0\)) does the same, so the sign is fixed entirely by the current \(y_i\):
\[ d_i=\begin{cases}-1,& y_i\ge 0,\\+1,& y_i<0,\end{cases} \qquad z_{i+1}=z_i-d_i\arctan(2^{-i}), \]
with \(z_0=0\). Since \(\sum_{i\ge0}\arctan(2^{-i})\approx1.7433\) rad (about \(99.9°\)), this converges for any starting angle in \(\left(-\frac{\pi}{2},\frac{\pi}{2}\right]\) — exactly the range \(\arg(x,y)\) falls into whenever \(x\ge0\). For \(x<0\), rotating the input by \(\pi\) first — which is just negating both coordinates — brings it into that range, at the cost of tracking which half-turn was applied:
\[ (x,y)\ \mapsto\ (-x,-y),\qquad z_0=\begin{cases}+\pi,& x<0,\ y\ge0,\\-\pi,& x<0,\ y<0.\end{cases} \]
As a check, tracing the loop on \((x,y)=(1,1)\), for which \(x\ge0\) so \(z_0=0\), against the exact target \(\operatorname{atan2}(1,1)=\pi/4\approx0.785398\):
| \(i\) | \(x_i\) | \(y_i\) | \(d_i\) | \(z_{i+1}\) |
|---|---|---|---|---|
| 0 | 1 | 1 | \(-1\) | 0.7854 |
| 1 | 2 | 0 | \(-1\) | 1.2490 |
| 2 | 2 | \(-1\) | \(+1\) | 1.0041 |
| 3 | 2.25 | \(-0.5\) | \(+1\) | 0.8797 |
| \(\vdots\) | … | … | ||
| 15 | 2.3285 | \(0.0000363\) | \(-1\) | 0.785413 |
Note how \(y_i\) does not shrink monotonically — it overshoots past \(0\) and back several times — while \(z\) still tightens around \(\pi/4\) at every step, closing in on it to within \(1.5\times10^{-5}\) rad after sixteen iterations, since each iteration adds roughly one more correct bit of angle.
Implementation
The table of angles \(\arctan(2^{-i})\) is fixed and only ever needs to be computed once, offline, with an ordinary atan() call; nothing inside the loop below evaluates a transcendental function:
#include <math.h>
#define FAST_ATAN2_PI 3.14159265358979323846f
/* atan(2^-i) for i = 0..15, computed once offline */
static const float cordic_atan_table[16] = {
0.78539816339744830961f, 0.46364760900080611621f, 0.24497866312686415417f, 0.12435499454676143503f,
0.06241880999595735066f, 0.03123983343026827626f, 0.01562372862047683080f, 0.00781234106010111150f,
0.00390623013196697182f, 0.00195312251647881879f, 0.00097656218955931946f, 0.00048828121119489829f,
0.00024414062014936177f, 0.00012207031310632503f, 0.00006103515617420877f, 0.00003051757811552610f
};
/* worst-case error after 16 iterations: well below 0.01 degrees */
float cordic_atan2(float y, float x) {
float z, x_new, y_new;
int i;
if (x == 0.0f && y == 0.0f) return 0.0f;
z = 0.0f;
if (x < 0.0f) {
z = y < 0.0f ? -FAST_ATAN2_PI : FAST_ATAN2_PI;
x = -x;
y = -y;
}
for (i = 0; i < 16; i++) {
float scale = 1.0f / (float)(1 << i); /* 2^-i */
if (y >= 0.0f) {
x_new = x + y * scale;
y_new = y - x * scale;
z += cordic_atan_table[i];
} else {
x_new = x - y * scale;
y_new = y + x * scale;
z -= cordic_atan_table[i];
}
x = x_new;
y = y_new;
}
return z;
} Sixteen iterations already push the error below \(0.01°\), past what the polynomial and rational approximations above reach; doubling the table toward the limits of float precision costs nothing but more loop iterations, each exactly as cheap as the last. What CORDIC does not offer is a smooth error curve: because \(y_i\) can flip sign from one iteration to the next near convergence, as in the trace above, nearby inputs can settle on opposite sides of that flip and accumulate their last few corrections in a different order. That shows up as small, non-smooth jitter rather than the steadily growing error of a truncated polynomial — a good reason to prefer one of the closed-form approximations above whenever a multiplier is available.
Choosing an Approximation
- Need the absolute cheapest option and can tolerate a few degrees of error (e.g. a rough sort by direction)? The diamond approximation needs no division, no branch on magnitude, and only one comparison.
- Need sub-degree accuracy with a predictable, smooth error curve for something like a control loop or a derivative? A quadratic-corrected linear approximation or the endpoint-matched rational form both land around \(0.2°\)–\(0.3°\) for two or three extra operations.
- Need better than a tenth of a degree, or correctness at the level of the last bit of a double? Use the cubic-refined form for the former, or fall back to a standard library
atan2for the latter. - Whichever is chosen, always special-case \(x=0,\,y=0\) explicitly rather than relying on the approximation to behave well at \(0/0\).
References
- Volder59 Volder, J. E. (1959). The CORDIC Trigonometric Computing Technique.