|
1 | 1 | pub mod f32 { |
2 | | - #[allow(unused_imports)] |
3 | | - use core; |
4 | | - |
| 2 | + /// Newton-Raphson square root implementation for f32. |
| 3 | + /// Uses bit manipulation for initial guess, then 3 iterations for ~6-7 decimal places. |
| 4 | + /// Accuracy: ~6-7 decimal places |
5 | 5 | #[cfg(not(feature = "std"))] |
6 | 6 | pub fn sqrt(x: f32) -> f32 { |
7 | | - if x >= 0.0 { |
8 | | - f32::from_bits((x.to_bits() + 0x3f80_0000) >> 1) |
9 | | - } else { |
10 | | - f32::NAN |
| 7 | + if x < 0.0 { |
| 8 | + return f32::NAN; |
| 9 | + } |
| 10 | + if x == 0.0 { |
| 11 | + return x; // preserves +0.0 and -0.0 |
| 12 | + } |
| 13 | + |
| 14 | + // Initial guess from bit manipulation: halve exponent, shift mantissa |
| 15 | + let bits = x.to_bits(); |
| 16 | + let exp = (bits >> 23) & 0xff; |
| 17 | + let mant = bits & 0x7fffff; |
| 18 | + |
| 19 | + let unbiased = exp as i32 - 127; |
| 20 | + let sqrt_exp = (unbiased / 2 + 127) as u32; |
| 21 | + let guess_bits = (sqrt_exp << 23) | (mant >> 1); |
| 22 | + let mut guess = f32::from_bits(guess_bits); |
| 23 | + |
| 24 | + for _ in 0..3 { |
| 25 | + guess = 0.5 * (guess + x / guess); |
11 | 26 | } |
| 27 | + guess |
12 | 28 | } |
13 | 29 | #[cfg(feature = "std")] |
| 30 | + #[inline] |
14 | 31 | pub fn sqrt(x: f32) -> f32 { |
15 | 32 | x.sqrt() |
16 | 33 | } |
17 | 34 | } |
18 | 35 |
|
19 | 36 | pub mod f64 { |
20 | | - #[allow(unused_imports)] |
21 | | - use core; |
22 | | - |
| 37 | + /// Newton-Raphson square root implementation for f64. |
| 38 | + /// Uses bit manipulation for initial guess, then 4 iterations for ~14-15 decimal places. |
| 39 | + /// Accuracy: ~14-15 decimal places |
23 | 40 | #[cfg(not(feature = "std"))] |
24 | 41 | pub fn sqrt(x: f64) -> f64 { |
25 | | - if x >= 0.0 { |
26 | | - f64::from_bits((x.to_bits() + 0x3f80_0000) >> 1) |
27 | | - } else { |
28 | | - f64::NAN |
| 42 | + if x < 0.0 { |
| 43 | + return f64::NAN; |
| 44 | + } |
| 45 | + if x == 0.0 { |
| 46 | + return x; // preserves +0.0 and -0.0 |
| 47 | + } |
| 48 | + |
| 49 | + // Initial guess from bit manipulation: halve exponent, shift mantissa |
| 50 | + let bits = x.to_bits(); |
| 51 | + let exp = (bits >> 52) & 0x7ff; |
| 52 | + let mant = bits & 0x000f_ffff_ffff_ffff; |
| 53 | + |
| 54 | + let unbiased = exp as i32 - 1023; |
| 55 | + let sqrt_exp = (unbiased / 2 + 1023) as u64; |
| 56 | + let guess_bits = (sqrt_exp << 52) | (mant >> 1); |
| 57 | + let mut guess = f64::from_bits(guess_bits); |
| 58 | + |
| 59 | + for _ in 0..4 { |
| 60 | + guess = 0.5 * (guess + x / guess); |
29 | 61 | } |
| 62 | + guess |
30 | 63 | } |
31 | 64 | #[cfg(feature = "std")] |
| 65 | + #[inline] |
32 | 66 | pub fn sqrt(x: f64) -> f64 { |
33 | 67 | x.sqrt() |
34 | 68 | } |
|
0 commit comments