Skip to content

Commit 58eaf27

Browse files
committed
Add newlib sqrtf
1 parent d56f74d commit 58eaf27

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

src/math/sqrtf.rs

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/* ef_sqrtf.c -- float version of e_sqrt.c.
2+
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
3+
*/
4+
5+
/*
6+
* ====================================================
7+
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8+
*
9+
* Developed at SunPro, a Sun Microsystems, Inc. business.
10+
* Permission to use, copy, modify, and distribute this
11+
* software is freely granted, provided that this notice
12+
* is preserved.
13+
* ====================================================
14+
*/
15+
16+
const ONE: f32 = 1.0;
17+
const TINY: f32 = 1.0e-30;
18+
19+
#[inline]
20+
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
21+
pub fn sqrtf(x: f32) -> f32 {
22+
use super::fdlibm::{FLT_UWORD_IS_FINITE, FLT_UWORD_IS_SUBNORMAL, FLT_UWORD_IS_ZERO};
23+
// On wasm32 we know that LLVM's intrinsic will compile to an optimized
24+
// `f32.sqrt` native instruction, so we can leverage this for both code size
25+
// and speed.
26+
llvm_intrinsically_optimized! {
27+
#[cfg(target_arch = "wasm32")] {
28+
return if x < 0.0 {
29+
::core::f32::NAN
30+
} else {
31+
unsafe { ::core::intrinsics::sqrtf32(x) }
32+
}
33+
}
34+
}
35+
36+
let mut z: f32;
37+
38+
let mut r: u32;
39+
let hx: u32;
40+
41+
let mut ix: i32;
42+
let mut s: i32;
43+
let mut q: i32;
44+
let mut m: i32;
45+
let mut t: i32;
46+
let mut i: i32;
47+
48+
ix = x.to_bits() as i32;
49+
hx = ix as u32 & 0x7fff_ffff;
50+
51+
/* take care of Inf and NaN */
52+
if !FLT_UWORD_IS_FINITE(hx) {
53+
return x * x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */
54+
}
55+
56+
/* take care of zero and -ves */
57+
if FLT_UWORD_IS_ZERO(hx) {
58+
return x; /* sqrt(+-0) = +-0 */
59+
}
60+
if ix < 0 {
61+
return (x - x) / (x - x); /* sqrt(-ve) = sNaN */
62+
}
63+
64+
/* normalize x */
65+
m = ix >> 23;
66+
if FLT_UWORD_IS_SUBNORMAL(hx) {
67+
/* subnormal x */
68+
i = 0;
69+
while ix & 0x0080_0000 == 0 {
70+
ix <<= 1;
71+
i += 1;
72+
}
73+
m -= i - 1;
74+
}
75+
m -= 127; /* unbias exponent */
76+
ix = (ix & 0x007f_ffff) | 0x0080_0000;
77+
/* odd m, double x to make it even */
78+
if m & 1 == 1 {
79+
ix += ix;
80+
}
81+
m >>= 1; /* m = [m/2] */
82+
83+
/* generate sqrt(x) bit by bit */
84+
ix += ix;
85+
q = 0;
86+
s = 0; /* q = sqrt(x) */
87+
r = 0x0100_0000; /* r = moving bit from right to left */
88+
89+
while r != 0 {
90+
t = s + r as i32;
91+
if t <= ix {
92+
s = t + r as i32;
93+
ix -= t;
94+
q += r as i32;
95+
}
96+
ix += ix;
97+
r >>= 1;
98+
}
99+
100+
/* use floating add to find out rounding direction */
101+
if ix != 0 {
102+
z = ONE - TINY; /* trigger inexact flag */
103+
if z >= ONE {
104+
z = ONE + TINY;
105+
if z > ONE {
106+
q += 2;
107+
} else {
108+
q += q & 1;
109+
}
110+
}
111+
}
112+
ix = (q >> 1) + 0x3f00_0000;
113+
ix += m << 23;
114+
f32::from_bits(ix as u32)
115+
}

0 commit comments

Comments
 (0)