1const RSQRT_TAB: [u16; 128] = [
10 0xb451,0xb2f0,0xb196,0xb044,0xaef9,0xadb6,0xac79,0xab43,
11 0xaa14,0xa8eb,0xa7c8,0xa6aa,0xa592,0xa480,0xa373,0xa26b,
12 0xa168,0xa06a,0x9f70,0x9e7b,0x9d8a,0x9c9d,0x9bb5,0x9ad1,
13 0x99f0,0x9913,0x983a,0x9765,0x9693,0x95c4,0x94f8,0x9430,
14 0x936b,0x92a9,0x91ea,0x912e,0x9075,0x8fbe,0x8f0a,0x8e59,
15 0x8daa,0x8cfe,0x8c54,0x8bac,0x8b07,0x8a64,0x89c4,0x8925,
16 0x8889,0x87ee,0x8756,0x86c0,0x862b,0x8599,0x8508,0x8479,
17 0x83ec,0x8361,0x82d8,0x8250,0x81c9,0x8145,0x80c2,0x8040,
18 0xff02,0xfd0e,0xfb25,0xf947,0xf773,0xf5aa,0xf3ea,0xf234,
19 0xf087,0xeee3,0xed47,0xebb3,0xea27,0xe8a3,0xe727,0xe5b2,
20 0xe443,0xe2dc,0xe17a,0xe020,0xdecb,0xdd7d,0xdc34,0xdaf1,
21 0xd9b3,0xd87b,0xd748,0xd61a,0xd4f1,0xd3cd,0xd2ad,0xd192,
22 0xd07b,0xcf69,0xce5b,0xcd51,0xcc4a,0xcb48,0xca4a,0xc94f,
23 0xc858,0xc764,0xc674,0xc587,0xc49d,0xc3b7,0xc2d4,0xc1f4,
24 0xc116,0xc03c,0xbf65,0xbe90,0xbdbe,0xbcef,0xbc23,0xbb59,
25 0xba91,0xb9cc,0xb90a,0xb84a,0xb78c,0xb6d0,0xb617,0xb560,
26];
27
28#[inline]
33fn mul32(a: u32, b: u32) -> u32 {
34 ((a as u64 * b as u64) >> 32) as u32
35}
36
37#[inline]
38fn mul64(a: u64, b: u64) -> u64 {
39 let ahi = a >> 32;
40 let alo = a & 0xffffffff;
41 let bhi = b >> 32;
42 let blo = b & 0xffffffff;
43 ahi * bhi + (ahi * blo >> 32) + (alo * bhi >> 32)
44}
45
46#[no_mangle]
51pub extern "C" fn sqrt(x: f64) -> f64 {
52 let ix = asuint64(x);
53 let mut top = ix >> 52;
54
55 if predict_false(top.wrapping_sub(0x001) >= 0x7ff - 0x001) {
57 if ix.wrapping_mul(2) == 0 {
59 return x;
60 }
61 if ix == 0x7ff0000000000000 {
62 return x;
63 }
64 if ix > 0x7ff0000000000000 {
65 return __math_invalid(x);
66 }
67 let ix2 = asuint64(x * p2d(52));
69 top = ix2 >> 52;
70 top -= 52;
71 return sqrt_inner(ix2, top);
73 }
74 sqrt_inner(ix, top)
75}
76
77#[inline]
78fn sqrt_inner(ix: u64, top: u64) -> f64 {
79 let mut top = top;
80 let mut m;
81
82 let even = top & 1;
83 m = (ix << 11) | 0x8000000000000000u64;
84 if even != 0 {
85 m >>= 1;
86 }
87 top = (top + 0x3ff) >> 1;
88
89 let three = 0xc0000000u64;
90
91 let i = ((ix >> 46) % 128) as usize;
92 let mut r = (RSQRT_TAB[i] as u64) << 16;
93 let mut s = mul32((m >> 32) as u32, r as u32) as u64;
95 let mut d = mul32(s as u32, r as u32) as u64;
97 let mut u = three.wrapping_sub(d);
98 r = (mul32(r as u32, u as u32) as u64) << 1;
99 s = (mul32(s as u32, u as u32) as u64) << 1;
101 d = mul32(s as u32, r as u32) as u64;
103 u = three.wrapping_sub(d);
104 r = (mul32(r as u32, u as u32) as u64) << 1;
105 r = r << 32;
107 s = mul64(m, r);
108 d = mul64(s, r);
109 u = (three << 32).wrapping_sub(d);
110 s = mul64(s, u);
111 s = (s.wrapping_sub(2)) >> 9;
113
114 let d0 = m.wrapping_shl(42).wrapping_sub(s.wrapping_mul(s));
115 let d1 = s.wrapping_sub(d0);
116 let d2 = d1.wrapping_add(s).wrapping_add(1);
117 let s = s.wrapping_add((d1 >> 63) & 1);
118 let mut s = s & 0x000fffffffffffff;
119 s |= top << 52;
120 let mut y = asdouble(s);
121 let tiny = if predict_false(d2 == 0) { 0u64 } else { 0x0010000000000000u64 };
123 let tiny = tiny | ((d1 ^ d2) & 0x8000000000000000);
124 let t = asdouble(tiny);
125 y = eval_as_double(y + t);
126 y
127}
128
129#[no_mangle]
134pub extern "C" fn sqrtf(x: f32) -> f32 {
135 let ix = asuint(x);
136 if predict_false(ix.wrapping_sub(0x00800000) >= 0x7f800000 - 0x00800000) {
137 if ix.wrapping_mul(2) == 0 {
139 return x;
140 }
141 if ix == 0x7f800000 {
142 return x;
143 }
144 if ix > 0x7f800000 {
145 return __math_invalidf(x);
146 }
147 let ix2 = asuint(x * p2f(23));
149 return sqrtf_inner(ix2.wrapping_sub(23 << 23));
150 }
151 sqrtf_inner(ix)
152}
153
154#[inline]
155fn sqrtf_inner(ix: u32) -> f32 {
156 let even = ix & 0x00800000;
157 let m1 = (ix << 8) | 0x80000000u32;
158 let m0 = (ix << 7) & 0x7fffffff;
159 let m = if even != 0 { m0 } else { m1 };
160
161 let mut ey = ix >> 1;
163 ey = ey.wrapping_add(0x3f800000 >> 1);
164 ey &= 0x7f800000;
165
166 let three = 0xc0000000u32;
167 let i = ((ix >> 17) % 128) as usize;
168 let mut r = (RSQRT_TAB[i] as u32) << 16;
169 let mut s = mul32(m, r);
170 let mut d = mul32(s, r);
171 let mut u = three.wrapping_sub(d);
172 r = mul32(r, u) << 1;
173 s = mul32(s, u) << 1;
174 d = mul32(s, r);
175 u = three.wrapping_sub(d);
176 s = mul32(s, u);
177 s = (s.wrapping_sub(1)) >> 6;
179
180 let d0 = m.wrapping_shl(16).wrapping_sub(s.wrapping_mul(s));
181 let d1 = s.wrapping_sub(d0);
182 let d2 = d1.wrapping_add(s).wrapping_add(1);
183 let s = s.wrapping_add((d1 >> 31) & 1);
184 let mut s = s & 0x007fffff;
185 s |= ey;
186 let mut y = asfloat(s);
187 let tiny = if predict_false(d2 == 0) { 0u32 } else { 0x01000000u32 };
189 let tiny = tiny | ((d1 ^ d2) & 0x80000000);
190 let t = asfloat(tiny);
191 y = eval_as_float(y + t);
192 y
193}
194
195#[no_mangle]
200pub extern "C" fn fmod(x: f64, y: f64) -> f64 {
201 let uxi = asuint64(x);
202 let uyi = asuint64(y);
203 let ex = ((uxi >> 52) & 0x7ff) as i32;
204 let ey = ((uyi >> 52) & 0x7ff) as i32;
205 let sx = uxi >> 63;
206
207 if uyi << 1 == 0 || is_nan(y) || ex == 0x7ff {
208 return (x * y) / (x * y);
209 }
210 if uxi << 1 <= uyi << 1 {
211 if uxi << 1 == uyi << 1 {
212 return 0.0 * x;
213 }
214 return x;
215 }
216
217 let mut uxi = uxi;
219 let mut uyi = uyi;
220 let mut ex = ex;
221 let mut ey = ey;
222
223 if ex == 0 {
224 let mut i = uxi << 12;
225 while (i as i64) >= 0 {
226 ex -= 1;
227 i <<= 1;
228 }
229 uxi <<= (-ex + 1) as u64;
230 } else {
231 uxi &= (-1i64 as u64) >> 12;
232 uxi |= 1u64 << 52;
233 }
234 if ey == 0 {
235 let mut i = uyi << 12;
236 while (i as i64) >= 0 {
237 ey -= 1;
238 i <<= 1;
239 }
240 uyi <<= (-ey + 1) as u64;
241 } else {
242 uyi &= (-1i64 as u64) >> 12;
243 uyi |= 1u64 << 52;
244 }
245
246 while ex > ey {
248 let i = uxi.wrapping_sub(uyi);
249 if (i as i64) >= 0 {
250 if i == 0 {
251 return 0.0 * x;
252 }
253 uxi = i;
254 }
255 uxi <<= 1;
256 ex -= 1;
257 }
258 let i = uxi.wrapping_sub(uyi);
259 if (i as i64) >= 0 {
260 if i == 0 {
261 return 0.0 * x;
262 }
263 uxi = i;
264 }
265 while uxi >> 52 == 0 {
266 uxi <<= 1;
267 ex -= 1;
268 }
269
270 if ex > 0 {
272 uxi -= 1u64 << 52;
273 uxi |= (ex as u64) << 52;
274 } else {
275 uxi >>= (-ex + 1) as u64;
276 }
277 uxi |= sx << 63;
278 asdouble(uxi)
279}
280
281#[no_mangle]
286pub extern "C" fn fmodf(x: f32, y: f32) -> f32 {
287 let uxi = asuint(x);
288 let uyi = asuint(y);
289 let ex = ((uxi >> 23) & 0xff) as i32;
290 let ey = ((uyi >> 23) & 0xff) as i32;
291 let sx = uxi & 0x80000000;
292
293 if uyi << 1 == 0 || is_nanf(y) || ex == 0xff {
294 return (x * y) / (x * y);
295 }
296 if uxi << 1 <= uyi << 1 {
297 if uxi << 1 == uyi << 1 {
298 return 0.0f32 * x;
299 }
300 return x;
301 }
302
303 let mut uxi = uxi;
305 let mut uyi = uyi;
306 let mut ex = ex;
307 let mut ey = ey;
308
309 if ex == 0 {
310 let mut i = uxi << 9;
311 while (i as i32) >= 0 {
312 ex -= 1;
313 i <<= 1;
314 }
315 uxi <<= (-ex + 1) as u32;
316 } else {
317 uxi &= (-1i32 as u32) >> 9;
318 uxi |= 1u32 << 23;
319 }
320 if ey == 0 {
321 let mut i = uyi << 9;
322 while (i as i32) >= 0 {
323 ey -= 1;
324 i <<= 1;
325 }
326 uyi <<= (-ey + 1) as u32;
327 } else {
328 uyi &= (-1i32 as u32) >> 9;
329 uyi |= 1u32 << 23;
330 }
331
332 while ex > ey {
334 let i = uxi.wrapping_sub(uyi);
335 if (i as i32) >= 0 {
336 if i == 0 {
337 return 0.0f32 * x;
338 }
339 uxi = i;
340 }
341 uxi <<= 1;
342 ex -= 1;
343 }
344 let i = uxi.wrapping_sub(uyi);
345 if (i as i32) >= 0 {
346 if i == 0 {
347 return 0.0f32 * x;
348 }
349 uxi = i;
350 }
351 while uxi >> 23 == 0 {
352 uxi <<= 1;
353 ex -= 1;
354 }
355
356 if ex > 0 {
358 uxi -= 1u32 << 23;
359 uxi |= (ex as u32) << 23;
360 } else {
361 uxi >>= (-ex + 1) as u32;
362 }
363 uxi |= sx;
364 asfloat(uxi)
365}