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