# Calculate other tangents which are related

I am using a small microcontroller, which has limited processing resources. I need to calculate the three tangents:

tan(theta)
tan(hdg + theta)
tan(90 - hdg + theta)


theta is virtually constant (it is a field of view); hdg may change. tan(theta) is provided by doing sin(theta)/cos(theta) (in my library), so that all tangents in total incur six trig function calls... which slows it down a lot.

Is it possible to calculate all of these at once?

-
You only need to compute tan(hdg) and tan(theta); the rest are expressible in terms of these two via the sum/difference of two angles formulae for the tangent. If tan(theta) is, as you say, virtually constant, you might get away with not changing it for a number of iterations... –  Ｊ. Ｍ. May 11 '11 at 9:18
Depending on the resolution/accuracy required, you can calculate a table at start time and store it, then interpolate to avoid all run time trig. I had an application where storing every 5 degrees was sufficient (only 19 lines) and even interpolation wasn't needed. Very fast then. –  Ross Millikan May 11 '11 at 13:26

Well, there are addition formulas for $\tan$:

\begin{align} \tan (v + u) = \frac{\tan v + \tan u}{1 - \tan v \tan u} \\ \tan (v - u) = \frac{\tan v - \tan u}{1 + \tan v \tan u} \end{align}

So you can compute $\tan(hdg)$ and $\tan(\theta)$ then plug them into the first formula to get $\tan(\theta+hdg)$.

For the other formula you get have $\tan (90^\circ - w) = \cot w = \frac{1}{\tan w}$ where $w = hdg - \theta$, i.e.

$$\tan (90^\circ - (hdg - \theta)) = \frac{1}{\tan (hdg-\theta)} = \frac{1}{\frac{\tan hdg - \tan \theta}{1+\tan hdg \tan \theta}} = \frac{1 + \tan hdg \tan \theta}{\tan hdg - \tan \theta}$$

so you can once again use your previously calculated values for $\tan \theta$ and $\tan hdg$.

You might want to look into another way of evaulating $\tan x$. If your angle $x$ is smaller than $22.5^\circ$ you can use the polynomial

$$\tan x \approx x + \frac{x^3}{3} + \frac{2x^5}{15} + \frac{17x^7}{315}$$

Note that this is for an angle in radians, so you have to convert your angle from degrees to radians by multiplying by $\frac{\pi}{180} \approx 0.0174533$ You probably want to evaulate this using Horner's rule. Depending on how sensitive things are you might be able to drop one (or two) terms.

If your angle is larger than $22.5^\circ$ (or what limit you find suitable), you can use the half angle formula $$\tan x = \frac{2 \tan \frac{x}{2}}{1-\tan^2 \frac{x}{2}}$$ or the reciprocal $$\tan x = \frac{1}{\tan (90^\circ - x)}$$ depending on how large your angle is.

I don't know if this will be quicker or not, but it might be worth a shot.

-
Actually, it might be better to use the Padé approximant $$\frac{x(x^2-15)}{6x^2-15}$$ instead of the series. The idea of using the double-angle formula is a good one. –  Ｊ. Ｍ. May 11 '11 at 11:05
@J.M., plotting $\tan x - p(x)$ where $p$ is either the series or the Padé approximant clearly shows that the Padé approximant is better. Haven't heard of this before, cool. –  Calle May 11 '11 at 11:22
If more accurate Padé approximants are needed, one way to obtain them is by appropriately truncating the continued fraction for the tangent. –  Ｊ. Ｍ. May 11 '11 at 11:28

If hdg changes by constant increments, you might want to implement the following formulae (found in Numerical Recipes)

$\cos(\theta+\delta) = \cos\theta-(\alpha\cos\theta+\beta\sin\theta)$

$\sin(\theta+\delta) = \sin\theta-(\alpha\sin\theta-\beta\cos\theta)$

$\alpha=2\sin^2\frac\delta2,\qquad\beta=\sin\delta$

The brackets indicate in which order the operations should be performed in order to minimize floating-point errors.

-
I note that these stable recursions are easily derived from the complex exponential form. Resist the urge to "simplify" $2\sin^2\frac\delta2$ to $1-\cos\delta$; the reason for using the former instead of the latter is that you avoid the subtractive cancellation inherent in computing $1-\cos\delta$ for "tiny" $\delta$ (hint: Maclaurin). –  Ｊ. Ｍ. May 11 '11 at 11:11