1const INVTRIG_PIO2_HI: f64 = asdouble(0x3FF921FB54442D18);
12const INVTRIG_PIO2_LO: f64 = asdouble(0x3C91A62633145C07);
13
14const INVTRIG_PS0: f64 = asdouble(0x3FC5555555555555);
15const INVTRIG_PS1: f64 = asdouble(0xBFD4D61203EB6F7D);
16const INVTRIG_PS2: f64 = asdouble(0x3FC9C1550E884455);
17const INVTRIG_PS3: f64 = asdouble(0xBFA48228B5688F3B);
18const INVTRIG_PS4: f64 = asdouble(0x3F49EFE07501B288);
19const INVTRIG_PS5: f64 = asdouble(0x3F023DE10DFDF709);
20const INVTRIG_QS1: f64 = asdouble(0xC0033A271C8A2D4B);
21const INVTRIG_QS2: f64 = asdouble(0x40002AE59C598AC8);
22const INVTRIG_QS3: f64 = asdouble(0xBFE6066C1B8D0159);
23const INVTRIG_QS4: f64 = asdouble(0x3FB3B8C5B12E9282);
24
25#[inline]
27fn invtrig_r(z: f64) -> f64 {
28 let p = z * (INVTRIG_PS0 + z * (INVTRIG_PS1 + z * (INVTRIG_PS2
29 + z * (INVTRIG_PS3 + z * (INVTRIG_PS4 + z * INVTRIG_PS5)))));
30 let q = 1.0 + z * (INVTRIG_QS1 + z * (INVTRIG_QS2 + z * (INVTRIG_QS3 + z * INVTRIG_QS4)));
31 p / q
32}
33
34#[no_mangle]
39pub unsafe extern "C" fn asin(x: f64) -> f64 {
40 let hx = get_high_word(x);
41 let ix = hx & 0x7fffffff;
42 if ix >= 0x3ff00000 {
44 let lx = get_low_word(x);
45 if (ix.wrapping_sub(0x3ff00000) | lx) == 0 {
46 return x * INVTRIG_PIO2_HI + asdouble(0x3870000000000000); }
49 return 0.0 / (x - x);
50 }
51 if ix < 0x3fe00000 {
53 if ix < 0x3e500000 && ix >= 0x00100000 {
55 return x;
56 }
57 return x + x * invtrig_r(x * x);
58 }
59 let z = (1.0 - fabs(x)) * 0.5;
61 let s = sqrt(z);
62 let r = invtrig_r(z);
63 let result;
64 if ix >= 0x3fef3333 {
65 result = INVTRIG_PIO2_HI - (2.0 * (s + s * r) - INVTRIG_PIO2_LO);
67 } else {
68 let mut f = s;
70 set_low_word(&mut f, 0);
71 let c = (z - f * f) / (s + f);
72 result = 0.5 * INVTRIG_PIO2_HI
73 - (2.0 * s * r - (INVTRIG_PIO2_LO - 2.0 * c) - (0.5 * INVTRIG_PIO2_HI - 2.0 * f));
74 }
75 if (hx >> 31) != 0 {
76 return -result;
77 }
78 result
79}
80
81#[no_mangle]
86pub unsafe extern "C" fn acos(x: f64) -> f64 {
87 let hx = get_high_word(x);
88 let ix = hx & 0x7fffffff;
89 if ix >= 0x3ff00000 {
91 let lx = get_low_word(x);
92 if (ix.wrapping_sub(0x3ff00000) | lx) == 0 {
93 if (hx >> 31) != 0 {
95 return 2.0 * INVTRIG_PIO2_HI + asdouble(0x3870000000000000); }
97 return 0.0;
98 }
99 return 0.0 / (x - x);
100 }
101 if ix < 0x3fe00000 {
103 if ix <= 0x3c600000 {
104 return INVTRIG_PIO2_HI + asdouble(0x3870000000000000); }
107 return INVTRIG_PIO2_HI - (x - (INVTRIG_PIO2_LO - x * invtrig_r(x * x)));
108 }
109 if (hx >> 31) != 0 {
111 let z = (1.0 + x) * 0.5;
112 let s = sqrt(z);
113 let w = invtrig_r(z) * s - INVTRIG_PIO2_LO;
114 return 2.0 * (INVTRIG_PIO2_HI - (s + w));
115 }
116 let z = (1.0 - x) * 0.5;
118 let s = sqrt(z);
119 let mut df = s;
120 set_low_word(&mut df, 0);
121 let c = (z - df * df) / (s + df);
122 let w = invtrig_r(z) * s + c;
123 2.0 * (df + w)
124}
125
126const INVTRIG_ATANHI: [f64; 4] = [
131 asdouble(0x3FDDAC670561BB4F), asdouble(0x3FE921FB54442D18), asdouble(0x3FEF730BD281F69B), asdouble(0x3FF921FB54442D18), ];
136
137const INVTRIG_ATANLO: [f64; 4] = [
138 asdouble(0x3C7A2B7F222F65E2), asdouble(0x3C81A62633145C07), asdouble(0x3C7007887AF0CBBD), asdouble(0x3C91A62633145C07), ];
143
144const INVTRIG_AT: [f64; 11] = [
145 asdouble(0x3FD555555555550D),
146 asdouble(0xBFC999999998EBC4),
147 asdouble(0x3FC24924920083FF),
148 asdouble(0xBFBC71C6FE231671),
149 asdouble(0x3FB745CDC54C206E),
150 asdouble(0xBFB3B0F2AF749A6D),
151 asdouble(0x3FB10D66A0D03D51),
152 asdouble(0xBFADDE2D52DEFD9A),
153 asdouble(0x3FA97B4B24760DEB),
154 asdouble(0xBFA2B4442C6A6C2F),
155 asdouble(0x3F90AD3AE322DA11),
156];
157
158#[no_mangle]
159pub unsafe extern "C" fn atan(x: f64) -> f64 {
160 let ix_raw = get_high_word(x);
161 let sign = ix_raw >> 31;
162 let mut ix = ix_raw & 0x7fffffff;
163 let mut x = x;
164
165 if ix >= 0x44100000 {
166 if is_nan(x) {
168 return x;
169 }
170 let z = INVTRIG_ATANHI[3] + asdouble(0x3870000000000000); return if sign != 0 { -z } else { z };
172 }
173
174 let id;
175 if ix < 0x3fdc0000 {
176 if ix < 0x3e400000 {
178 if ix < 0x00100000 {
180 force_eval(x as f32);
182 }
183 return x;
184 }
185 id = -1i32;
186 } else {
187 x = fabs(x);
188 ix = get_high_word(x) & 0x7fffffff;
189 if ix < 0x3ff30000 {
190 if ix < 0x3fe60000 {
192 id = 0;
194 x = (2.0 * x - 1.0) / (2.0 + x);
195 } else {
196 id = 1;
198 x = (x - 1.0) / (x + 1.0);
199 }
200 } else {
201 if ix < 0x40038000 {
202 id = 2;
204 x = (x - 1.5) / (1.0 + 1.5 * x);
205 } else {
206 id = 3;
208 x = -1.0 / x;
209 }
210 }
211 }
212
213 let z = x * x;
215 let w = z * z;
216 let s1 = z * (INVTRIG_AT[0] + w * (INVTRIG_AT[2] + w * (INVTRIG_AT[4]
218 + w * (INVTRIG_AT[6] + w * (INVTRIG_AT[8] + w * INVTRIG_AT[10])))));
219 let s2 = w * (INVTRIG_AT[1] + w * (INVTRIG_AT[3] + w * (INVTRIG_AT[5]
220 + w * (INVTRIG_AT[7] + w * INVTRIG_AT[9]))));
221 if id < 0 {
222 return x - x * (s1 + s2);
223 }
224 let z = INVTRIG_ATANHI[id as usize] - (x * (s1 + s2) - INVTRIG_ATANLO[id as usize] - x);
225 if sign != 0 { -z } else { z }
226}
227
228const INVTRIG_PI: f64 = asdouble(0x400921FB54442D18);
233const INVTRIG_PI_LO: f64 = asdouble(0x3CA1A62633145C07);
234
235#[no_mangle]
236pub unsafe extern "C" fn atan2(y: f64, x: f64) -> f64 {
237 if is_nan(x) || is_nan(y) {
238 return x + y;
239 }
240 let mut ix: u32 = 0;
241 let mut lx: u32 = 0;
242 let mut iy: u32 = 0;
243 let mut ly: u32 = 0;
244 extract_words(&mut ix, &mut lx, x);
245 extract_words(&mut iy, &mut ly, y);
246
247 if (ix.wrapping_sub(0x3ff00000) | lx) == 0 {
248 return atan(y);
250 }
251 let m = ((iy >> 31) & 1) | ((ix >> 30) & 2); ix &= 0x7fffffff;
253 iy &= 0x7fffffff;
254
255 if (iy | ly) == 0 {
257 match m {
258 0 | 1 => return y, 2 => return INVTRIG_PI, 3 => return -INVTRIG_PI, _ => core::hint::unreachable_unchecked(),
262 }
263 }
264 if (ix | lx) == 0 {
266 return if (m & 1) != 0 { -INVTRIG_PI / 2.0 } else { INVTRIG_PI / 2.0 };
267 }
268 if ix == 0x7ff00000 {
270 if iy == 0x7ff00000 {
271 match m {
272 0 => return INVTRIG_PI / 4.0, 1 => return -INVTRIG_PI / 4.0, 2 => return 3.0 * INVTRIG_PI / 4.0, 3 => return -3.0 * INVTRIG_PI / 4.0, _ => core::hint::unreachable_unchecked(),
277 }
278 } else {
279 match m {
280 0 => return 0.0, 1 => return -0.0, 2 => return INVTRIG_PI, 3 => return -INVTRIG_PI, _ => core::hint::unreachable_unchecked(),
285 }
286 }
287 }
288 if ix.wrapping_add(64 << 20) < iy || iy == 0x7ff00000 {
290 return if (m & 1) != 0 { -INVTRIG_PI / 2.0 } else { INVTRIG_PI / 2.0 };
291 }
292
293 let z;
295 if (m & 2) != 0 && iy.wrapping_add(64 << 20) < ix {
296 z = 0.0;
298 } else {
299 z = atan(fabs(y / x));
300 }
301 match m {
302 0 => z, 1 => -z, 2 => INVTRIG_PI - (z - INVTRIG_PI_LO), _ => (z - INVTRIG_PI_LO) - INVTRIG_PI, }
307}
308
309const INVTRIG_PS0_F: f32 = 1.6666586697e-01;
314const INVTRIG_PS1_F: f32 = -4.2743422091e-02;
315const INVTRIG_PS2_F: f32 = -8.6563630030e-03;
316const INVTRIG_QS1_F: f32 = -7.0662963390e-01;
317
318#[inline]
320fn invtrig_rf(z: f32) -> f32 {
321 let p = z * (INVTRIG_PS0_F + z * (INVTRIG_PS1_F + z * INVTRIG_PS2_F));
322 let q = 1.0f32 + z * INVTRIG_QS1_F;
323 p / q
324}
325
326const INVTRIG_PIO2_F: f64 = asdouble(0x3FF921FB54442D18);
331
332#[no_mangle]
333pub unsafe extern "C" fn asinf(x: f32) -> f32 {
334 let hx = get_float_word(x);
335 let ix = hx & 0x7fffffff;
336 if ix >= 0x3f800000 {
338 if ix == 0x3f800000 {
339 return (x as f64 * INVTRIG_PIO2_F + asdouble(0x3870000000000000)) as f32; }
342 return 0.0f32 / (x - x); }
344 if ix < 0x3f000000 {
346 if ix < 0x39800000 && ix >= 0x00800000 {
348 return x;
349 }
350 return x + x * invtrig_rf(x * x);
351 }
352 let z = (1.0f32 - fabsf(x)) * 0.5f32;
354 let s = sqrt(z as f64);
355 let result = INVTRIG_PIO2_F - 2.0 * (s + s * invtrig_rf(z) as f64);
356 let result = result as f32;
357 if (hx >> 31) != 0 {
358 return -result;
359 }
360 result
361}
362
363const INVTRIG_PIO2_HI_F: f32 = asfloat(0x3fc90fda);
368const INVTRIG_PIO2_LO_F: f32 = asfloat(0x33a22168);
369
370#[no_mangle]
371pub unsafe extern "C" fn acosf(x: f32) -> f32 {
372 let hx = get_float_word(x);
373 let ix = hx & 0x7fffffff;
374 if ix >= 0x3f800000 {
376 if ix == 0x3f800000 {
377 if (hx >> 31) != 0 {
378 return 2.0 * INVTRIG_PIO2_HI_F + asfloat(0x03800000); }
380 return 0.0;
381 }
382 return 0.0f32 / (x - x);
383 }
384 if ix < 0x3f000000 {
386 if ix <= 0x32800000 {
387 return INVTRIG_PIO2_HI_F + asfloat(0x03800000); }
390 return INVTRIG_PIO2_HI_F - (x - (INVTRIG_PIO2_LO_F - x * invtrig_rf(x * x)));
391 }
392 if (hx >> 31) != 0 {
394 let z = (1.0f32 + x) * 0.5f32;
395 let s = sqrtf(z);
396 let w = invtrig_rf(z) * s - INVTRIG_PIO2_LO_F;
397 return 2.0 * (INVTRIG_PIO2_HI_F - (s + w));
398 }
399 let z = (1.0f32 - x) * 0.5f32;
401 let s = sqrtf(z);
402 let hz = get_float_word(s);
403 let df = asfloat(hz & 0xfffff000);
404 let c = (z - df * df) / (s + df);
405 let w = invtrig_rf(z) * s + c;
406 2.0 * (df + w)
407}
408
409const INVTRIG_ATANHI_F: [f32; 4] = [
414 asfloat(0x3eed6338), asfloat(0x3f490fda), asfloat(0x3f7b985e), asfloat(0x3fc90fda), ];
419
420const INVTRIG_ATANLO_F: [f32; 4] = [
421 asfloat(0x31ac3769), asfloat(0x33222168), asfloat(0x33140fb4), asfloat(0x33a22168), ];
426
427const INVTRIG_AT_F: [f32; 5] = [
428 3.3333328366e-01,
429 -1.9999158382e-01,
430 1.4253635705e-01,
431 -1.0648017377e-01,
432 6.1687607318e-02,
433];
434
435#[no_mangle]
436pub unsafe extern "C" fn atanf(x: f32) -> f32 {
437 let ix_raw = get_float_word(x);
438 let sign = ix_raw >> 31;
439 let mut ix = ix_raw & 0x7fffffff;
440 let mut x = x;
441
442 if ix >= 0x4c800000 {
443 if is_nanf(x) {
445 return x;
446 }
447 let z = INVTRIG_ATANHI_F[3] + asfloat(0x03800000); return if sign != 0 { -z } else { z };
449 }
450
451 let id;
452 if ix < 0x3ee00000 {
453 if ix < 0x39800000 {
455 if ix < 0x00800000 {
457 force_eval(x * x);
459 }
460 return x;
461 }
462 id = -1i32;
463 } else {
464 x = fabsf(x);
465 ix = get_float_word(x) & 0x7fffffff;
466 if ix < 0x3f980000 {
467 if ix < 0x3f300000 {
469 id = 0;
471 x = (2.0f32 * x - 1.0f32) / (2.0f32 + x);
472 } else {
473 id = 1;
475 x = (x - 1.0f32) / (x + 1.0f32);
476 }
477 } else {
478 if ix < 0x401c0000 {
479 id = 2;
481 x = (x - 1.5f32) / (1.0f32 + 1.5f32 * x);
482 } else {
483 id = 3;
485 x = -1.0f32 / x;
486 }
487 }
488 }
489
490 let z = x * x;
492 let w = z * z;
493 let s1 = z * (INVTRIG_AT_F[0] + w * (INVTRIG_AT_F[2] + w * INVTRIG_AT_F[4]));
494 let s2 = w * (INVTRIG_AT_F[1] + w * INVTRIG_AT_F[3]);
495 if id < 0 {
496 return x - x * (s1 + s2);
497 }
498 let z = INVTRIG_ATANHI_F[id as usize] - ((x * (s1 + s2) - INVTRIG_ATANLO_F[id as usize]) - x);
499 if sign != 0 { -z } else { z }
500}
501
502const INVTRIG_PI_F: f32 = asfloat(0x40490fdb);
507const INVTRIG_PI_LO_F: f32 = asfloat(0xb3bbbd2e);
508
509#[no_mangle]
510pub unsafe extern "C" fn atan2f(y: f32, x: f32) -> f32 {
511 if is_nanf(x) || is_nanf(y) {
512 return x + y;
513 }
514 let ix: u32;
515 let iy: u32;
516 ix = get_float_word(x);
517 iy = get_float_word(y);
518
519 if ix == 0x3f800000 {
520 return atanf(y);
522 }
523 let m = ((iy >> 31) & 1) | ((ix >> 30) & 2); let ix = ix & 0x7fffffff;
525 let iy = iy & 0x7fffffff;
526
527 if iy == 0 {
529 match m {
530 0 | 1 => return y, 2 => return INVTRIG_PI_F, 3 => return -INVTRIG_PI_F, _ => core::hint::unreachable_unchecked(),
534 }
535 }
536 if ix == 0 {
538 return if (m & 1) != 0 { -INVTRIG_PI_F / 2.0 } else { INVTRIG_PI_F / 2.0 };
539 }
540 if ix == 0x7f800000 {
542 if iy == 0x7f800000 {
543 match m {
544 0 => return INVTRIG_PI_F / 4.0, 1 => return -INVTRIG_PI_F / 4.0, 2 => return 3.0 * INVTRIG_PI_F / 4.0, 3 => return -3.0 * INVTRIG_PI_F / 4.0, _ => core::hint::unreachable_unchecked(),
549 }
550 } else {
551 match m {
552 0 => return 0.0f32, 1 => return -0.0f32, 2 => return INVTRIG_PI_F, 3 => return -INVTRIG_PI_F, _ => core::hint::unreachable_unchecked(),
557 }
558 }
559 }
560 if ix.wrapping_add(26 << 23) < iy || iy == 0x7f800000 {
562 return if (m & 1) != 0 { -INVTRIG_PI_F / 2.0 } else { INVTRIG_PI_F / 2.0 };
563 }
564
565 let z;
567 if (m & 2) != 0 && iy.wrapping_add(26 << 23) < ix {
568 z = 0.0f32;
570 } else {
571 z = atanf(fabsf(y / x));
572 }
573 match m {
574 0 => z, 1 => -z, 2 => INVTRIG_PI_F - (z - INVTRIG_PI_LO_F), _ => (z - INVTRIG_PI_LO_F) - INVTRIG_PI_F, }
579}