diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index bf31f36d22d25..c8162f90fd775 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -456,6 +456,23 @@ impl Float for f32 { #[inline] fn rsqrt(self) -> f32 { self.sqrt().recip() } + /// The reciprocal of the square root of a number, quickly using + /// Newton's method to approximate the value. + /// Originally seen in Quake arena + fn fast_rsqrt(self) -> f32 { + let mut i: i32; + let mut x2: f32; + let mut y: f32; + + y = self; + x2 = y * 0.5; + i = unsafe{cast::transmute::(y)}; // stark lack of evil floating point bit + i = 0x5f3759df - ( i >> 1 ); // level hacking + y = unsafe{cast::transmute::(i)}; + y = y * (1.5 - (x2 * y * y)); + y + } + #[inline] fn cbrt(self) -> f32 { unsafe { cmath::cbrtf(self) } diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 39eba0825fc3c..75fb4e263e8b5 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -464,6 +464,28 @@ impl Float for f64 { #[inline] fn rsqrt(self) -> f64 { self.sqrt().recip() } + /// The reciprocal of the square root of a number, quickly using + /// Newton's method to approximate the value. For f64 values, + /// the calculations are still done with 32 bit precision due to + /// the math not working the same way in higher bit types. If you're + /// calculating the "fast" inverse square root, however, this should + /// not be a major problem + /// Originally seen in Quake arena + fn fast_rsqrt(self) -> f64 { + let mut i: i32; + let mut x2: f32; + let mut y: f32; + + y = self as f32; + x2 = y * 0.5; + i = unsafe{cast::transmute::(y)}; // stark lack of evil floating point bit + i = 0x5f3759df - ( i >> 1 ); // level hacking + y = unsafe{cast::transmute::(i)}; + y = y * (1.5 - (x2 * y * y)); + y as f64 + } + + #[inline] fn cbrt(self) -> f64 { unsafe { cmath::cbrt(self) } diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index c498892e76cb4..5b0d251b156f1 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -428,6 +428,8 @@ pub trait Float: Signed + Primitive { fn sqrt(self) -> Self; /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. fn rsqrt(self) -> Self; + /// Take the fast reciprocal (inverse) square root of a number, `1/sqrt(x)` + fn fast_rsqrt(self) -> Self; /// Take the cubic root of a number. fn cbrt(self) -> Self; /// Calculate the length of the hypotenuse of a right-angle triangle given