This commit is contained in:
Mark 2025-02-11 15:44:42 -08:00
parent 9993a8f286
commit cee894389d
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
3 changed files with 32 additions and 8 deletions

View File

@ -1,9 +1,5 @@
#import "@local/handout:0.1.0": *
// Another look:
// - Highlight that left-shift divides the exponent by two
// - Highlight that log(ri) is already in its integer representation
//
// Bonus:
// - Floats vs fixed point
// - Float density

View File

@ -128,7 +128,7 @@ Find the $s$, $E$, and $F$ we get if we interpret this bit string as a `float`.
#v(1fr)
#definition()
#definition(label: "floatdef")
The final value of a float with sign $s$, exponent $E$, and fraction $F$ is
$

View File

@ -162,8 +162,6 @@ So, $0.045$ is the $epsilon$ used by Quake. \
Online sources state that this constant was generated by trial-and-error, \
though it is fairly close to the ideal $epsilon$.
#v(4mm)
#remark()
And now, we're done! \
We've shown that `Q_sqrt(x)` approximates $1/sqrt(x)$ fairly well, \
@ -172,9 +170,39 @@ thanks to the approximation $log(1+a) = a + epsilon$.
#v(2mm)
Notably, `Q_sqrt` uses _zero_ divisions or multiplications (`>>` doesn't count). \
This makes it _very_ fast when compared to more traditional approximation techniques like Fourier series.
This makes it _very_ fast when compared to more traditional approximation techniques (i.e, Taylor series).
#v(2mm)
In the case of _Quake_, this is very important. 3D graphics require thousands of inverse-square-root calculations to render a single frame#footnote[e.g, to generate normal vectors], which is not an easy task for a Playstation running at 300MHz.
#instructornote[
Let $x$ be a bit string. If we assume $x_f$ is positive and $E$ is even, then
$
(x #text[`>>`] 1)_f = 2^((E div 2) - 127) times (1 + (F div 2) / (2^(23)))
$
Notably: a right-shift divides the exponent of $x_f$ by two, \
which is, of course, a square root!
#v(2mm)
This intuition is hand-wavy, though: \
If $E$ is odd, its lowest-order bit becomes the highest-order bit of $F$ when we shift $x$ right. \
Also, a right shift doesn't divide the _entire_ exponent, skipping the $-127$ offset. \
#v(2mm)
Remarkably, this intuition is still somewhat correct. \
The bits align _just so_, and our approximation still works.
#v(8mm)
One can think of the fast inverse root as a "digital slide rule": \
The integer representation of $x_f$ already contains $log_2(x_f)$, offset and scaled. \
By subtracting and dividing in "log space", we effectively invert and root $x_f$!
After all,
$
- 1 / 2 log_2(n_f) = 1 / sqrt(n_f)
$
]