2025-01-22 21:50:31 -08:00
|
|
|
\section{The Fast Inverse Square Root}
|
|
|
|
|
|
|
|
The following code is present in \textit{Quake III Arena} (1999):
|
|
|
|
\lstset{
|
|
|
|
breaklines=false,
|
|
|
|
numbersep=5pt,
|
|
|
|
xrightmargin=0in
|
|
|
|
}
|
|
|
|
\begin{lstlisting}[language=C]
|
|
|
|
float Q_rsqrt( float number ) {
|
|
|
|
long i = * ( long * ) &number;
|
|
|
|
i = 0x5f3759df - ( i >> 1 );
|
|
|
|
return * ( float * ) &i;
|
|
|
|
}
|
|
|
|
\end{lstlisting}
|
|
|
|
|
2025-02-08 14:54:40 -08:00
|
|
|
This code defines
|
|
|
|
a function \texttt{Q\_rsqrt} that consumes a float named
|
|
|
|
\texttt{number} and approximates its inverse square root (in other words, \texttt{Q\_rsqrt} computes $1/\sqrt{\texttt{number}}$).
|
2025-01-22 21:50:31 -08:00
|
|
|
|
2025-02-08 14:54:40 -08:00
|
|
|
\vspace{2mm}
|
2025-01-22 21:50:31 -08:00
|
|
|
|
|
|
|
If we rewrite this using the notation we're familiar with, we get the following:
|
|
|
|
\begin{equation*}
|
2025-02-08 14:54:40 -08:00
|
|
|
\texttt{Q\_sqrt}(n_i) = 6240089 - (n_i \div 2) \approx \frac{1}{\sqrt{n_f}}
|
2025-01-22 21:50:31 -08:00
|
|
|
\end{equation*}
|
2025-02-08 14:54:40 -08:00
|
|
|
$6240089$ is the decimal value of hex \texttt{0x5f3759df}. \par
|
|
|
|
It is a magic number hard-coded into the function.
|
2025-01-22 21:50:31 -08:00
|
|
|
|
2025-02-08 14:54:40 -08:00
|
|
|
\vspace{2mm}
|
|
|
|
|
|
|
|
Our goal in this section is to understand why this works. \par
|
|
|
|
How are we able to approximate $\frac{1}{\sqrt{x}}$ by only subtracting and dividing by two??
|
2025-01-22 21:50:31 -08:00
|
|
|
|
|
|
|
\problem{}
|
2025-02-08 14:54:40 -08:00
|
|
|
Using basic log rules, rewrite $\log_2(1 / \sqrt{x})$ in terms of $\log_2(x)$.
|
2025-01-22 21:50:31 -08:00
|
|
|
|
|
|
|
\begin{solution}
|
2025-02-08 14:54:40 -08:00
|
|
|
\begin{equation*}
|
|
|
|
\log_2(1 / \sqrt{x}) = \frac{-1}{2}\log_2(x)
|
|
|
|
\end{equation*}
|
|
|
|
\end{solution}
|
|
|
|
|
|
|
|
|
|
|
|
\vfill
|
|
|
|
|
2025-01-22 21:50:31 -08:00
|
|
|
|
2025-02-08 14:54:40 -08:00
|
|
|
\problem{}
|
|
|
|
Find the exact value of $\kappa$ in terms of $\varepsilon$. \par
|
|
|
|
\note{Remember, $\varepsilon$ is the correction term in the approximation $\log_2(1 + a) = a + \varepsilon$.}
|
|
|
|
|
|
|
|
\begin{solution}
|
|
|
|
Say $g_f = \frac{1}{\sqrt{n_f}}$ (i.e, $g_f$ is the value we want to compute). We then have:
|
2025-01-22 21:50:31 -08:00
|
|
|
\begin{align*}
|
|
|
|
\log_2(g_f)
|
|
|
|
&=\log_2(\frac{1}{\sqrt{n_f}}) \\
|
|
|
|
&=\frac{-1}{2}\log_2(n_f) \\
|
|
|
|
&=\frac{-1}{2}\left( \frac{n_i}{2^{23}} + \varepsilon - 127 \right)
|
|
|
|
\end{align*}
|
|
|
|
But we also know that
|
|
|
|
\begin{align*}
|
|
|
|
\log_2(g_f)
|
|
|
|
&=\frac{g_i}{2^{23}} + \varepsilon - 127
|
|
|
|
\end{align*}
|
|
|
|
So,
|
|
|
|
\begin{align*}
|
|
|
|
\frac{g_i}{2^{23}} + \varepsilon - 127
|
|
|
|
&=\frac{-1}{2}\left( \frac{n_i}{2^{23}} + \varepsilon - 127 \right) \\
|
|
|
|
\frac{g_i}{2^{23}}
|
|
|
|
&=\frac{-1}{2}\left( \frac{n_i}{2^{23}} \right) + \frac{3}{2}(\varepsilon - 127) \\
|
|
|
|
g_i
|
|
|
|
&=\frac{-1}{2}\left(n_i \right) + 2^{23}\frac{3}{2}(\varepsilon - 127) \\
|
|
|
|
&=2^{23}\frac{3}{2}(\varepsilon - 127) - \frac{n_i}{2}
|
|
|
|
\end{align*}
|
|
|
|
|
2025-02-08 14:54:40 -08:00
|
|
|
and thus $\kappa = 2^{23}\frac{3}{2}(\varepsilon - 127)$.
|
2025-01-22 21:50:31 -08:00
|
|
|
\end{solution}
|
|
|
|
|
2025-02-08 14:54:40 -08:00
|
|
|
\vfill
|
|
|
|
|
2025-01-22 21:50:31 -08:00
|
|
|
\pagebreak
|