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#[cfg(target_arch = "x86_64")]
51#[no_mangle]
52pub extern "C" fn sqrt(x: f64) -> f64 {
53 let y: f64;
57 unsafe {
58 core::arch::asm!(
59 "sqrtsd {y}, {x}",
60 y = out(xmm_reg) y,
61 x = in(xmm_reg) x,
62 options(nomem, nostack)
63 );
64 }
65 y
66}
67
68#[cfg(not(target_arch = "x86_64"))]
69#[no_mangle]
70pub extern "C" fn sqrt(x: f64) -> f64 {
71 let ix = asuint64(x);
72 let mut top = ix >> 52;
73
74 if predict_false(top.wrapping_sub(0x001) >= 0x7ff - 0x001) {
76 if ix.wrapping_mul(2) == 0 {
78 return x;
79 }
80 if ix == 0x7ff0000000000000 {
81 return x;
82 }
83 if ix > 0x7ff0000000000000 {
84 return __math_invalid(x);
85 }
86 let ix2 = asuint64(x * p2d(52));
88 top = ix2 >> 52;
89 top -= 52;
90 return sqrt_inner(ix2, top);
92 }
93 sqrt_inner(ix, top)
94}
95
96#[inline]
97fn sqrt_inner(ix: u64, top: u64) -> f64 {
98 let mut top = top;
99 let mut m;
100
101 let even = top & 1;
102 m = (ix << 11) | 0x8000000000000000u64;
103 if even != 0 {
104 m >>= 1;
105 }
106 top = (top + 0x3ff) >> 1;
107
108 let three = 0xc0000000u64;
109
110 let i = ((ix >> 46) % 128) as usize;
111 let mut r = (RSQRT_TAB[i] as u64) << 16;
112 let mut s = mul32((m >> 32) as u32, r as u32) as u64;
114 let mut d = mul32(s as u32, r as u32) as u64;
116 let mut u = three.wrapping_sub(d);
117 r = (mul32(r as u32, u as u32) as u64) << 1;
118 s = (mul32(s as u32, u as u32) as u64) << 1;
120 d = mul32(s as u32, r as u32) as u64;
122 u = three.wrapping_sub(d);
123 r = (mul32(r as u32, u as u32) as u64) << 1;
124 r = r << 32;
126 s = mul64(m, r);
127 d = mul64(s, r);
128 u = (three << 32).wrapping_sub(d);
129 s = mul64(s, u);
130 s = (s.wrapping_sub(2)) >> 9;
132
133 let d0 = m.wrapping_shl(42).wrapping_sub(s.wrapping_mul(s));
134 let d1 = s.wrapping_sub(d0);
135 let d2 = d1.wrapping_add(s).wrapping_add(1);
136 let s = s.wrapping_add((d1 >> 63) & 1);
137 let mut s = s & 0x000fffffffffffff;
138 s |= top << 52;
139 let mut y = asdouble(s);
140 let tiny = if predict_false(d2 == 0) { 0u64 } else { 0x0010000000000000u64 };
142 let tiny = tiny | ((d1 ^ d2) & 0x8000000000000000);
143 let t = asdouble(tiny);
144 y = eval_as_double(y + t);
145 y
146}
147
148#[no_mangle]
153pub extern "C" fn sqrtf(x: f32) -> f32 {
154 let ix = asuint(x);
155 if predict_false(ix.wrapping_sub(0x00800000) >= 0x7f800000 - 0x00800000) {
156 if ix.wrapping_mul(2) == 0 {
158 return x;
159 }
160 if ix == 0x7f800000 {
161 return x;
162 }
163 if ix > 0x7f800000 {
164 return __math_invalidf(x);
165 }
166 let ix2 = asuint(x * p2f(23));
168 return sqrtf_inner(ix2.wrapping_sub(23 << 23));
169 }
170 sqrtf_inner(ix)
171}
172
173#[inline]
174fn sqrtf_inner(ix: u32) -> f32 {
175 let even = ix & 0x00800000;
176 let m1 = (ix << 8) | 0x80000000u32;
177 let m0 = (ix << 7) & 0x7fffffff;
178 let m = if even != 0 { m0 } else { m1 };
179
180 let mut ey = ix >> 1;
182 ey = ey.wrapping_add(0x3f800000 >> 1);
183 ey &= 0x7f800000;
184
185 let three = 0xc0000000u32;
186 let i = ((ix >> 17) % 128) as usize;
187 let mut r = (RSQRT_TAB[i] as u32) << 16;
188 let mut s = mul32(m, r);
189 let mut d = mul32(s, r);
190 let mut u = three.wrapping_sub(d);
191 r = mul32(r, u) << 1;
192 s = mul32(s, u) << 1;
193 d = mul32(s, r);
194 u = three.wrapping_sub(d);
195 s = mul32(s, u);
196 s = (s.wrapping_sub(1)) >> 6;
198
199 let d0 = m.wrapping_shl(16).wrapping_sub(s.wrapping_mul(s));
200 let d1 = s.wrapping_sub(d0);
201 let d2 = d1.wrapping_add(s).wrapping_add(1);
202 let s = s.wrapping_add((d1 >> 31) & 1);
203 let mut s = s & 0x007fffff;
204 s |= ey;
205 let mut y = asfloat(s);
206 let tiny = if predict_false(d2 == 0) { 0u32 } else { 0x01000000u32 };
208 let tiny = tiny | ((d1 ^ d2) & 0x80000000);
209 let t = asfloat(tiny);
210 y = eval_as_float(y + t);
211 y
212}
213
214#[no_mangle]
219pub extern "C" fn fmod(x: f64, y: f64) -> f64 {
220 let uxi = asuint64(x);
221 let uyi = asuint64(y);
222 let ex = ((uxi >> 52) & 0x7ff) as i32;
223 let ey = ((uyi >> 52) & 0x7ff) as i32;
224 let sx = uxi >> 63;
225
226 if uyi << 1 == 0 || is_nan(y) || ex == 0x7ff {
227 return (x * y) / (x * y);
228 }
229 if uxi << 1 <= uyi << 1 {
230 if uxi << 1 == uyi << 1 {
231 return 0.0 * x;
232 }
233 return x;
234 }
235
236 let mut uxi = uxi;
238 let mut uyi = uyi;
239 let mut ex = ex;
240 let mut ey = ey;
241
242 if ex == 0 {
243 let mut i = uxi << 12;
244 while (i as i64) >= 0 {
245 ex -= 1;
246 i <<= 1;
247 }
248 uxi <<= (-ex + 1) as u64;
249 } else {
250 uxi &= (-1i64 as u64) >> 12;
251 uxi |= 1u64 << 52;
252 }
253 if ey == 0 {
254 let mut i = uyi << 12;
255 while (i as i64) >= 0 {
256 ey -= 1;
257 i <<= 1;
258 }
259 uyi <<= (-ey + 1) as u64;
260 } else {
261 uyi &= (-1i64 as u64) >> 12;
262 uyi |= 1u64 << 52;
263 }
264
265 while ex > ey {
267 let i = uxi.wrapping_sub(uyi);
268 if (i as i64) >= 0 {
269 if i == 0 {
270 return 0.0 * x;
271 }
272 uxi = i;
273 }
274 uxi <<= 1;
275 ex -= 1;
276 }
277 let i = uxi.wrapping_sub(uyi);
278 if (i as i64) >= 0 {
279 if i == 0 {
280 return 0.0 * x;
281 }
282 uxi = i;
283 }
284 while uxi >> 52 == 0 {
285 uxi <<= 1;
286 ex -= 1;
287 }
288
289 if ex > 0 {
291 uxi -= 1u64 << 52;
292 uxi |= (ex as u64) << 52;
293 } else {
294 uxi >>= (-ex + 1) as u64;
295 }
296 uxi |= sx << 63;
297 asdouble(uxi)
298}
299
300#[no_mangle]
305pub extern "C" fn fmodf(x: f32, y: f32) -> f32 {
306 let uxi = asuint(x);
307 let uyi = asuint(y);
308 let ex = ((uxi >> 23) & 0xff) as i32;
309 let ey = ((uyi >> 23) & 0xff) as i32;
310 let sx = uxi & 0x80000000;
311
312 if uyi << 1 == 0 || is_nanf(y) || ex == 0xff {
313 return (x * y) / (x * y);
314 }
315 if uxi << 1 <= uyi << 1 {
316 if uxi << 1 == uyi << 1 {
317 return 0.0f32 * x;
318 }
319 return x;
320 }
321
322 let mut uxi = uxi;
324 let mut uyi = uyi;
325 let mut ex = ex;
326 let mut ey = ey;
327
328 if ex == 0 {
329 let mut i = uxi << 9;
330 while (i as i32) >= 0 {
331 ex -= 1;
332 i <<= 1;
333 }
334 uxi <<= (-ex + 1) as u32;
335 } else {
336 uxi &= (-1i32 as u32) >> 9;
337 uxi |= 1u32 << 23;
338 }
339 if ey == 0 {
340 let mut i = uyi << 9;
341 while (i as i32) >= 0 {
342 ey -= 1;
343 i <<= 1;
344 }
345 uyi <<= (-ey + 1) as u32;
346 } else {
347 uyi &= (-1i32 as u32) >> 9;
348 uyi |= 1u32 << 23;
349 }
350
351 while ex > ey {
353 let i = uxi.wrapping_sub(uyi);
354 if (i as i32) >= 0 {
355 if i == 0 {
356 return 0.0f32 * x;
357 }
358 uxi = i;
359 }
360 uxi <<= 1;
361 ex -= 1;
362 }
363 let i = uxi.wrapping_sub(uyi);
364 if (i as i32) >= 0 {
365 if i == 0 {
366 return 0.0f32 * x;
367 }
368 uxi = i;
369 }
370 while uxi >> 23 == 0 {
371 uxi <<= 1;
372 ex -= 1;
373 }
374
375 if ex > 0 {
377 uxi -= 1u32 << 23;
378 uxi |= (ex as u32) << 23;
379 } else {
380 uxi >>= (-ex + 1) as u32;
381 }
382 uxi |= sx;
383 asfloat(uxi)
384}