I implemented the famous Quake inverse sqrt function in Rust!

191 points PlumpyD

So, I recently started learning the Rust language about 2 weeks ago, and I have been exploring some more advanced concepts of memory management and bit manipulation. (Including potentially the most dangerous of them all, std::mem::transmute)

TL;DR: Here is the code, more context and explanation below.

fn quake_rsqrt(number: f32) -> f32 {
    let mut y: f32 = number;
    unsafe {
        let mut i: i32 = std::mem::transmute::<f32, i32>(y);
        i = 0x5F375A86 - (i >> 1);
        y = std::mem::transmute::<i32, f32>(i);
    } 
    y * (1.5 - (number * 0.5 * y * y)) 
}

As a way to practice and apply what I have learned, I implemented the infamous, bit-hacking, most-memory-unsafe Quake inverse square root function, with a few variations for speed and accuracy! I have eliminated 2 of the variable allocations, saving a few instructions, as well as reducing the revisions to only one in the process. It is also using the derived, more-accurate "0x5F375A86" constant instead of the original "0x5F3759DF". Because of this, even with only one iterative revision, the resulting answer is within about 0.1% of the correct answer! If anyone would like a better explanation for the how the algorithm works, here is a link to a video from Nemean on YouTube. He gives a great explanation of the whole thing. https://www.youtube.com/watch?v=p8u\_k2LIZyo

That's all I've got for now, but I thought it was a fun thought experiment to try doing the most unsafe memory hacks with the most type-safe, memory-safe language I could think of! lol Hope you all have a great day!

​

Edit: Updated with even better code using the to\_bits and from\_bits functions. Full credit to /u/Shadow0133!

fn quake_rsqrt(number: f32) -> f32 {
    let mut i: i32 = number.to_bits() as i32;
    i = 0x5F375A86 - (i >> 1);
    let y = f32::from_bits(i as u32);
    y * (1.5 - (number * 0.5 * y * y))
}