1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "softfloat.h"
23#include "fpu/softfloat-macros.h"
24#include "softfloat_fpsp_tables.h"
25
26#define pi_exp 0x4000
27#define piby2_exp 0x3FFF
28#define pi_sig LIT64(0xc90fdaa22168c235)
29
30static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status)
31{
32 if (floatx80_is_signaling_nan(a, status)) {
33 float_raise(float_flag_invalid, status);
34 }
35
36 if (status->default_nan_mode) {
37 return floatx80_default_nan(status);
38 }
39
40 return floatx80_maybe_silence_nan(a, status);
41}
42
43
44
45
46
47
48floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status)
49{
50 flag aSign, zSign;
51 int32_t aExp, bExp, expDiff;
52 uint64_t aSig0, aSig1, bSig;
53 uint64_t qTemp, term0, term1;
54
55 aSig0 = extractFloatx80Frac(a);
56 aExp = extractFloatx80Exp(a);
57 aSign = extractFloatx80Sign(a);
58 bSig = extractFloatx80Frac(b);
59 bExp = extractFloatx80Exp(b);
60
61 if (aExp == 0x7FFF) {
62 if ((uint64_t) (aSig0 << 1)
63 || ((bExp == 0x7FFF) && (uint64_t) (bSig << 1))) {
64 return propagateFloatx80NaN(a, b, status);
65 }
66 goto invalid;
67 }
68 if (bExp == 0x7FFF) {
69 if ((uint64_t) (bSig << 1)) {
70 return propagateFloatx80NaN(a, b, status);
71 }
72 return a;
73 }
74 if (bExp == 0) {
75 if (bSig == 0) {
76 invalid:
77 float_raise(float_flag_invalid, status);
78 return floatx80_default_nan(status);
79 }
80 normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
81 }
82 if (aExp == 0) {
83 if ((uint64_t) (aSig0 << 1) == 0) {
84 return a;
85 }
86 normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
87 }
88 bSig |= LIT64(0x8000000000000000);
89 zSign = aSign;
90 expDiff = aExp - bExp;
91 aSig1 = 0;
92 if (expDiff < 0) {
93 return a;
94 }
95 qTemp = (bSig <= aSig0);
96 if (qTemp) {
97 aSig0 -= bSig;
98 }
99 expDiff -= 64;
100 while (0 < expDiff) {
101 qTemp = estimateDiv128To64(aSig0, aSig1, bSig);
102 qTemp = (2 < qTemp) ? qTemp - 2 : 0;
103 mul64To128(bSig, qTemp, &term0, &term1);
104 sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
105 shortShift128Left(aSig0, aSig1, 62, &aSig0, &aSig1);
106 }
107 expDiff += 64;
108 if (0 < expDiff) {
109 qTemp = estimateDiv128To64(aSig0, aSig1, bSig);
110 qTemp = (2 < qTemp) ? qTemp - 2 : 0;
111 qTemp >>= 64 - expDiff;
112 mul64To128(bSig, qTemp << (64 - expDiff), &term0, &term1);
113 sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
114 shortShift128Left(0, bSig, 64 - expDiff, &term0, &term1);
115 while (le128(term0, term1, aSig0, aSig1)) {
116 ++qTemp;
117 sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
118 }
119 }
120 return
121 normalizeRoundAndPackFloatx80(
122 80, zSign, bExp + expDiff, aSig0, aSig1, status);
123}
124
125
126
127
128
129
130floatx80 floatx80_getman(floatx80 a, float_status *status)
131{
132 flag aSign;
133 int32_t aExp;
134 uint64_t aSig;
135
136 aSig = extractFloatx80Frac(a);
137 aExp = extractFloatx80Exp(a);
138 aSign = extractFloatx80Sign(a);
139
140 if (aExp == 0x7FFF) {
141 if ((uint64_t) (aSig << 1)) {
142 return propagateFloatx80NaNOneArg(a , status);
143 }
144 float_raise(float_flag_invalid , status);
145 return floatx80_default_nan(status);
146 }
147
148 if (aExp == 0) {
149 if (aSig == 0) {
150 return packFloatx80(aSign, 0, 0);
151 }
152 normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
153 }
154
155 return roundAndPackFloatx80(status->floatx80_rounding_precision, aSign,
156 0x3FFF, aSig, 0, status);
157}
158
159
160
161
162
163
164floatx80 floatx80_getexp(floatx80 a, float_status *status)
165{
166 flag aSign;
167 int32_t aExp;
168 uint64_t aSig;
169
170 aSig = extractFloatx80Frac(a);
171 aExp = extractFloatx80Exp(a);
172 aSign = extractFloatx80Sign(a);
173
174 if (aExp == 0x7FFF) {
175 if ((uint64_t) (aSig << 1)) {
176 return propagateFloatx80NaNOneArg(a , status);
177 }
178 float_raise(float_flag_invalid , status);
179 return floatx80_default_nan(status);
180 }
181
182 if (aExp == 0) {
183 if (aSig == 0) {
184 return packFloatx80(aSign, 0, 0);
185 }
186 normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
187 }
188
189 return int32_to_floatx80(aExp - 0x3FFF, status);
190}
191
192
193
194
195
196
197
198
199
200floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
201{
202 flag aSign, bSign;
203 int32_t aExp, bExp, shiftCount;
204 uint64_t aSig, bSig;
205
206 aSig = extractFloatx80Frac(a);
207 aExp = extractFloatx80Exp(a);
208 aSign = extractFloatx80Sign(a);
209 bSig = extractFloatx80Frac(b);
210 bExp = extractFloatx80Exp(b);
211 bSign = extractFloatx80Sign(b);
212
213 if (bExp == 0x7FFF) {
214 if ((uint64_t) (bSig << 1) ||
215 ((aExp == 0x7FFF) && (uint64_t) (aSig << 1))) {
216 return propagateFloatx80NaN(a, b, status);
217 }
218 float_raise(float_flag_invalid , status);
219 return floatx80_default_nan(status);
220 }
221 if (aExp == 0x7FFF) {
222 if ((uint64_t) (aSig << 1)) {
223 return propagateFloatx80NaN(a, b, status);
224 }
225 return packFloatx80(aSign, floatx80_infinity.high,
226 floatx80_infinity.low);
227 }
228 if (aExp == 0) {
229 if (aSig == 0) {
230 return packFloatx80(aSign, 0, 0);
231 }
232 if (bExp < 0x3FFF) {
233 return a;
234 }
235 normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
236 }
237
238 if (bExp < 0x3FFF) {
239 return a;
240 }
241
242 if (0x400F < bExp) {
243 aExp = bSign ? -0x6001 : 0xE000;
244 return roundAndPackFloatx80(status->floatx80_rounding_precision,
245 aSign, aExp, aSig, 0, status);
246 }
247
248 shiftCount = 0x403E - bExp;
249 bSig >>= shiftCount;
250 aExp = bSign ? (aExp - bSig) : (aExp + bSig);
251
252 return roundAndPackFloatx80(status->floatx80_rounding_precision,
253 aSign, aExp, aSig, 0, status);
254}
255
256floatx80 floatx80_move(floatx80 a, float_status *status)
257{
258 flag aSign;
259 int32_t aExp;
260 uint64_t aSig;
261
262 aSig = extractFloatx80Frac(a);
263 aExp = extractFloatx80Exp(a);
264 aSign = extractFloatx80Sign(a);
265
266 if (aExp == 0x7FFF) {
267 if ((uint64_t)(aSig << 1)) {
268 return propagateFloatx80NaNOneArg(a, status);
269 }
270 return a;
271 }
272 if (aExp == 0) {
273 if (aSig == 0) {
274 return a;
275 }
276 normalizeRoundAndPackFloatx80(status->floatx80_rounding_precision,
277 aSign, aExp, aSig, 0, status);
278 }
279 return roundAndPackFloatx80(status->floatx80_rounding_precision, aSign,
280 aExp, aSig, 0, status);
281}
282
283
284
285
286
287
288#define one_exp 0x3FFF
289#define one_sig LIT64(0x8000000000000000)
290
291
292
293
294
295static int32_t floatx80_make_compact(int32_t aExp, uint64_t aSig)
296{
297 return (aExp << 16) | (aSig >> 48);
298}
299
300
301
302
303
304floatx80 floatx80_lognp1(floatx80 a, float_status *status)
305{
306 flag aSign;
307 int32_t aExp;
308 uint64_t aSig, fSig;
309
310 int8_t user_rnd_mode, user_rnd_prec;
311
312 int32_t compact, j, k;
313 floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu;
314
315 aSig = extractFloatx80Frac(a);
316 aExp = extractFloatx80Exp(a);
317 aSign = extractFloatx80Sign(a);
318
319 if (aExp == 0x7FFF) {
320 if ((uint64_t) (aSig << 1)) {
321 propagateFloatx80NaNOneArg(a, status);
322 }
323 if (aSign) {
324 float_raise(float_flag_invalid, status);
325 return floatx80_default_nan(status);
326 }
327 return packFloatx80(0, floatx80_infinity.high, floatx80_infinity.low);
328 }
329
330 if (aExp == 0 && aSig == 0) {
331 return packFloatx80(aSign, 0, 0);
332 }
333
334 if (aSign && aExp >= one_exp) {
335 if (aExp == one_exp && aSig == one_sig) {
336 float_raise(float_flag_divbyzero, status);
337 packFloatx80(aSign, floatx80_infinity.high, floatx80_infinity.low);
338 }
339 float_raise(float_flag_invalid, status);
340 return floatx80_default_nan(status);
341 }
342
343 if (aExp < 0x3f99 || (aExp == 0x3f99 && aSig == one_sig)) {
344
345 float_raise(float_flag_inexact, status);
346 return floatx80_move(a, status);
347 }
348
349 user_rnd_mode = status->float_rounding_mode;
350 user_rnd_prec = status->floatx80_rounding_precision;
351 status->float_rounding_mode = float_round_nearest_even;
352 status->floatx80_rounding_precision = 80;
353
354 compact = floatx80_make_compact(aExp, aSig);
355
356 fp0 = a;
357 fp1 = a;
358
359 fp0 = floatx80_add(fp0, float32_to_floatx80(make_float32(0x3F800000),
360 status), status);
361
362 aExp = extractFloatx80Exp(fp0);
363 aSig = extractFloatx80Frac(fp0);
364
365 compact = floatx80_make_compact(aExp, aSig);
366
367 if (compact < 0x3FFE8000 || compact > 0x3FFFC000) {
368
369 k = aExp - 0x3FFF;
370 fp1 = int32_to_floatx80(k, status);
371
372 fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000);
373 j = (fSig >> 56) & 0x7E;
374
375 f = packFloatx80(0, 0x3FFF, fSig);
376 fp0 = packFloatx80(0, 0x3FFF, aSig);
377
378 fp0 = floatx80_sub(fp0, f, status);
379
380 lp1cont1:
381
382 fp0 = floatx80_mul(fp0, log_tbl[j], status);
383 logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC));
384 klog2 = floatx80_mul(fp1, logof2, status);
385 fp2 = floatx80_mul(fp0, fp0, status);
386
387 fp3 = fp2;
388 fp1 = fp2;
389
390 fp1 = floatx80_mul(fp1, float64_to_floatx80(
391 make_float64(0x3FC2499AB5E4040B), status),
392 status);
393 fp2 = floatx80_mul(fp2, float64_to_floatx80(
394 make_float64(0xBFC555B5848CB7DB), status),
395 status);
396 fp1 = floatx80_add(fp1, float64_to_floatx80(
397 make_float64(0x3FC99999987D8730), status),
398 status);
399 fp2 = floatx80_add(fp2, float64_to_floatx80(
400 make_float64(0xBFCFFFFFFF6F7E97), status),
401 status);
402 fp1 = floatx80_mul(fp1, fp3, status);
403 fp2 = floatx80_mul(fp2, fp3, status);
404 fp1 = floatx80_add(fp1, float64_to_floatx80(
405 make_float64(0x3FD55555555555A4), status),
406 status);
407 fp2 = floatx80_add(fp2, float64_to_floatx80(
408 make_float64(0xBFE0000000000008), status),
409 status);
410 fp1 = floatx80_mul(fp1, fp3, status);
411 fp2 = floatx80_mul(fp2, fp3, status);
412 fp1 = floatx80_mul(fp1, fp0, status);
413 fp0 = floatx80_add(fp0, fp2, status);
414
415 fp1 = floatx80_add(fp1, log_tbl[j + 1],
416 status);
417 fp0 = floatx80_add(fp0, fp1, status);
418
419 status->float_rounding_mode = user_rnd_mode;
420 status->floatx80_rounding_precision = user_rnd_prec;
421
422 a = floatx80_add(fp0, klog2, status);
423
424 float_raise(float_flag_inexact, status);
425
426 return a;
427 } else if (compact < 0x3FFEF07D || compact > 0x3FFF8841) {
428
429
430 fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000);
431 f = packFloatx80(0, 0x3FFF, fSig);
432 j = (fSig >> 56) & 0x7E;
433
434 if (compact >= 0x3FFF8000) {
435
436 fp0 = floatx80_sub(float32_to_floatx80(make_float32(0x3F800000),
437 status), f, status);
438 fp0 = floatx80_add(fp0, fp1, status);
439 fp1 = packFloatx80(0, 0, 0);
440 } else {
441
442 fp0 = floatx80_sub(float32_to_floatx80(make_float32(0x40000000),
443 status), f, status);
444 fp1 = floatx80_add(fp1, fp1, status);
445 fp0 = floatx80_add(fp0, fp1, status);
446 fp1 = packFloatx80(1, one_exp, one_sig);
447 }
448 goto lp1cont1;
449 } else {
450
451 fp1 = floatx80_add(fp1, fp1, status);
452 fp0 = floatx80_add(fp0, float32_to_floatx80(make_float32(0x3F800000),
453 status), status);
454
455
456 fp1 = floatx80_div(fp1, fp0, status);
457 saveu = fp1;
458 fp0 = floatx80_mul(fp1, fp1, status);
459 fp1 = floatx80_mul(fp0, fp0, status);
460
461 fp3 = float64_to_floatx80(make_float64(0x3F175496ADD7DAD6),
462 status);
463 fp2 = float64_to_floatx80(make_float64(0x3F3C71C2FE80C7E0),
464 status);
465 fp3 = floatx80_mul(fp3, fp1, status);
466 fp2 = floatx80_mul(fp2, fp1, status);
467 fp3 = floatx80_add(fp3, float64_to_floatx80(
468 make_float64(0x3F624924928BCCFF), status),
469 status);
470 fp2 = floatx80_add(fp2, float64_to_floatx80(
471 make_float64(0x3F899999999995EC), status),
472 status);
473 fp1 = floatx80_mul(fp1, fp3, status);
474 fp2 = floatx80_mul(fp2, fp0, status);
475 fp1 = floatx80_add(fp1, float64_to_floatx80(
476 make_float64(0x3FB5555555555555), status),
477 status);
478
479 fp0 = floatx80_mul(fp0, saveu, status);
480 fp1 = floatx80_add(fp1, fp2,
481 status);
482 fp0 = floatx80_mul(fp0, fp1,
483 status);
484
485 status->float_rounding_mode = user_rnd_mode;
486 status->floatx80_rounding_precision = user_rnd_prec;
487
488 a = floatx80_add(fp0, saveu, status);
489
490
491 float_raise(float_flag_inexact, status);
492
493
494 return a;
495 }
496}
497
498
499
500
501
502floatx80 floatx80_logn(floatx80 a, float_status *status)
503{
504 flag aSign;
505 int32_t aExp;
506 uint64_t aSig, fSig;
507
508 int8_t user_rnd_mode, user_rnd_prec;
509
510 int32_t compact, j, k, adjk;
511 floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu;
512
513 aSig = extractFloatx80Frac(a);
514 aExp = extractFloatx80Exp(a);
515 aSign = extractFloatx80Sign(a);
516
517 if (aExp == 0x7FFF) {
518 if ((uint64_t) (aSig << 1)) {
519 propagateFloatx80NaNOneArg(a, status);
520 }
521 if (aSign == 0) {
522 return packFloatx80(0, floatx80_infinity.high,
523 floatx80_infinity.low);
524 }
525 }
526
527 adjk = 0;
528
529 if (aExp == 0) {
530 if (aSig == 0) {
531 float_raise(float_flag_divbyzero, status);
532 return packFloatx80(1, floatx80_infinity.high,
533 floatx80_infinity.low);
534 }
535 if ((aSig & one_sig) == 0) {
536 normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
537 adjk = -100;
538 aExp += 100;
539 a = packFloatx80(aSign, aExp, aSig);
540 }
541 }
542
543 if (aSign) {
544 float_raise(float_flag_invalid, status);
545 return floatx80_default_nan(status);
546 }
547
548 user_rnd_mode = status->float_rounding_mode;
549 user_rnd_prec = status->floatx80_rounding_precision;
550 status->float_rounding_mode = float_round_nearest_even;
551 status->floatx80_rounding_precision = 80;
552
553 compact = floatx80_make_compact(aExp, aSig);
554
555 if (compact < 0x3FFEF07D || compact > 0x3FFF8841) {
556
557 k = aExp - 0x3FFF;
558 k += adjk;
559 fp1 = int32_to_floatx80(k, status);
560
561 fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000);
562 j = (fSig >> 56) & 0x7E;
563
564 f = packFloatx80(0, 0x3FFF, fSig);
565 fp0 = packFloatx80(0, 0x3FFF, aSig);
566
567 fp0 = floatx80_sub(fp0, f, status);
568
569
570 fp0 = floatx80_mul(fp0, log_tbl[j], status);
571 logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC));
572 klog2 = floatx80_mul(fp1, logof2, status);
573 fp2 = floatx80_mul(fp0, fp0, status);
574
575 fp3 = fp2;
576 fp1 = fp2;
577
578 fp1 = floatx80_mul(fp1, float64_to_floatx80(
579 make_float64(0x3FC2499AB5E4040B), status),
580 status);
581 fp2 = floatx80_mul(fp2, float64_to_floatx80(
582 make_float64(0xBFC555B5848CB7DB), status),
583 status);
584 fp1 = floatx80_add(fp1, float64_to_floatx80(
585 make_float64(0x3FC99999987D8730), status),
586 status);
587 fp2 = floatx80_add(fp2, float64_to_floatx80(
588 make_float64(0xBFCFFFFFFF6F7E97), status),
589 status);
590 fp1 = floatx80_mul(fp1, fp3, status);
591 fp2 = floatx80_mul(fp2, fp3, status);
592 fp1 = floatx80_add(fp1, float64_to_floatx80(
593 make_float64(0x3FD55555555555A4), status),
594 status);
595 fp2 = floatx80_add(fp2, float64_to_floatx80(
596 make_float64(0xBFE0000000000008), status),
597 status);
598 fp1 = floatx80_mul(fp1, fp3, status);
599 fp2 = floatx80_mul(fp2, fp3, status);
600 fp1 = floatx80_mul(fp1, fp0, status);
601 fp0 = floatx80_add(fp0, fp2, status);
602
603 fp1 = floatx80_add(fp1, log_tbl[j + 1],
604 status);
605 fp0 = floatx80_add(fp0, fp1, status);
606
607 status->float_rounding_mode = user_rnd_mode;
608 status->floatx80_rounding_precision = user_rnd_prec;
609
610 a = floatx80_add(fp0, klog2, status);
611
612 float_raise(float_flag_inexact, status);
613
614 return a;
615 } else {
616 fp0 = a;
617 fp1 = a;
618 fp1 = floatx80_sub(fp1, float32_to_floatx80(make_float32(0x3F800000),
619 status), status);
620 fp0 = floatx80_add(fp0, float32_to_floatx80(make_float32(0x3F800000),
621 status), status);
622 fp1 = floatx80_add(fp1, fp1, status);
623
624
625 fp1 = floatx80_div(fp1, fp0, status);
626 saveu = fp1;
627 fp0 = floatx80_mul(fp1, fp1, status);
628 fp1 = floatx80_mul(fp0, fp0, status);
629
630 fp3 = float64_to_floatx80(make_float64(0x3F175496ADD7DAD6),
631 status);
632 fp2 = float64_to_floatx80(make_float64(0x3F3C71C2FE80C7E0),
633 status);
634 fp3 = floatx80_mul(fp3, fp1, status);
635 fp2 = floatx80_mul(fp2, fp1, status);
636 fp3 = floatx80_add(fp3, float64_to_floatx80(
637 make_float64(0x3F624924928BCCFF), status),
638 status);
639 fp2 = floatx80_add(fp2, float64_to_floatx80(
640 make_float64(0x3F899999999995EC), status),
641 status);
642 fp1 = floatx80_mul(fp1, fp3, status);
643 fp2 = floatx80_mul(fp2, fp0, status);
644 fp1 = floatx80_add(fp1, float64_to_floatx80(
645 make_float64(0x3FB5555555555555), status),
646 status);
647
648 fp0 = floatx80_mul(fp0, saveu, status);
649 fp1 = floatx80_add(fp1, fp2, status);
650 fp0 = floatx80_mul(fp0, fp1,
651 status);
652
653 status->float_rounding_mode = user_rnd_mode;
654 status->floatx80_rounding_precision = user_rnd_prec;
655
656 a = floatx80_add(fp0, saveu, status);
657
658
659 float_raise(float_flag_inexact, status);
660
661
662 return a;
663 }
664}
665
666
667
668
669
670floatx80 floatx80_log10(floatx80 a, float_status *status)
671{
672 flag aSign;
673 int32_t aExp;
674 uint64_t aSig;
675
676 int8_t user_rnd_mode, user_rnd_prec;
677
678 floatx80 fp0, fp1;
679
680 aSig = extractFloatx80Frac(a);
681 aExp = extractFloatx80Exp(a);
682 aSign = extractFloatx80Sign(a);
683
684 if (aExp == 0x7FFF) {
685 if ((uint64_t) (aSig << 1)) {
686 propagateFloatx80NaNOneArg(a, status);
687 }
688 if (aSign == 0) {
689 return packFloatx80(0, floatx80_infinity.high,
690 floatx80_infinity.low);
691 }
692 }
693
694 if (aExp == 0 && aSig == 0) {
695 float_raise(float_flag_divbyzero, status);
696 return packFloatx80(1, floatx80_infinity.high,
697 floatx80_infinity.low);
698 }
699
700 if (aSign) {
701 float_raise(float_flag_invalid, status);
702 return floatx80_default_nan(status);
703 }
704
705 user_rnd_mode = status->float_rounding_mode;
706 user_rnd_prec = status->floatx80_rounding_precision;
707 status->float_rounding_mode = float_round_nearest_even;
708 status->floatx80_rounding_precision = 80;
709
710 fp0 = floatx80_logn(a, status);
711 fp1 = packFloatx80(0, 0x3FFD, LIT64(0xDE5BD8A937287195));
712
713 status->float_rounding_mode = user_rnd_mode;
714 status->floatx80_rounding_precision = user_rnd_prec;
715
716 a = floatx80_mul(fp0, fp1, status);
717
718 float_raise(float_flag_inexact, status);
719
720 return a;
721}
722
723
724
725
726
727floatx80 floatx80_log2(floatx80 a, float_status *status)
728{
729 flag aSign;
730 int32_t aExp;
731 uint64_t aSig;
732
733 int8_t user_rnd_mode, user_rnd_prec;
734
735 floatx80 fp0, fp1;
736
737 aSig = extractFloatx80Frac(a);
738 aExp = extractFloatx80Exp(a);
739 aSign = extractFloatx80Sign(a);
740
741 if (aExp == 0x7FFF) {
742 if ((uint64_t) (aSig << 1)) {
743 propagateFloatx80NaNOneArg(a, status);
744 }
745 if (aSign == 0) {
746 return packFloatx80(0, floatx80_infinity.high,
747 floatx80_infinity.low);
748 }
749 }
750
751 if (aExp == 0) {
752 if (aSig == 0) {
753 float_raise(float_flag_divbyzero, status);
754 return packFloatx80(1, floatx80_infinity.high,
755 floatx80_infinity.low);
756 }
757 normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
758 }
759
760 if (aSign) {
761 float_raise(float_flag_invalid, status);
762 return floatx80_default_nan(status);
763 }
764
765 user_rnd_mode = status->float_rounding_mode;
766 user_rnd_prec = status->floatx80_rounding_precision;
767 status->float_rounding_mode = float_round_nearest_even;
768 status->floatx80_rounding_precision = 80;
769
770 if (aSig == one_sig) {
771 status->float_rounding_mode = user_rnd_mode;
772 status->floatx80_rounding_precision = user_rnd_prec;
773
774 a = int32_to_floatx80(aExp - 0x3FFF, status);
775 } else {
776 fp0 = floatx80_logn(a, status);
777 fp1 = packFloatx80(0, 0x3FFF, LIT64(0xB8AA3B295C17F0BC));
778
779 status->float_rounding_mode = user_rnd_mode;
780 status->floatx80_rounding_precision = user_rnd_prec;
781
782 a = floatx80_mul(fp0, fp1, status);
783 }
784
785 float_raise(float_flag_inexact, status);
786
787 return a;
788}
789
790
791
792
793
794floatx80 floatx80_etox(floatx80 a, float_status *status)
795{
796 flag aSign;
797 int32_t aExp;
798 uint64_t aSig;
799
800 int8_t user_rnd_mode, user_rnd_prec;
801
802 int32_t compact, n, j, k, m, m1;
803 floatx80 fp0, fp1, fp2, fp3, l2, scale, adjscale;
804 flag adjflag;
805
806 aSig = extractFloatx80Frac(a);
807 aExp = extractFloatx80Exp(a);
808 aSign = extractFloatx80Sign(a);
809
810 if (aExp == 0x7FFF) {
811 if ((uint64_t) (aSig << 1)) {
812 return propagateFloatx80NaNOneArg(a, status);
813 }
814 if (aSign) {
815 return packFloatx80(0, 0, 0);
816 }
817 return packFloatx80(0, floatx80_infinity.high,
818 floatx80_infinity.low);
819 }
820
821 if (aExp == 0 && aSig == 0) {
822 return packFloatx80(0, one_exp, one_sig);
823 }
824
825 user_rnd_mode = status->float_rounding_mode;
826 user_rnd_prec = status->floatx80_rounding_precision;
827 status->float_rounding_mode = float_round_nearest_even;
828 status->floatx80_rounding_precision = 80;
829
830 adjflag = 0;
831
832 if (aExp >= 0x3FBE) {
833 compact = floatx80_make_compact(aExp, aSig);
834
835 if (compact < 0x400CB167) {
836 fp0 = a;
837 fp1 = a;
838 fp0 = floatx80_mul(fp0, float32_to_floatx80(
839 make_float32(0x42B8AA3B), status),
840 status);
841 adjflag = 0;
842 n = floatx80_to_int32(fp0, status);
843 fp0 = int32_to_floatx80(n, status);
844
845 j = n & 0x3F;
846 m = n / 64;
847 if (n < 0 && j) {
848
849
850
851 m--;
852 }
853 m += 0x3FFF;
854
855 expcont1:
856 fp2 = fp0;
857 fp0 = floatx80_mul(fp0, float32_to_floatx80(
858 make_float32(0xBC317218), status),
859 status);
860 l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6));
861 fp2 = floatx80_mul(fp2, l2, status);
862 fp0 = floatx80_add(fp0, fp1, status);
863 fp0 = floatx80_add(fp0, fp2, status);
864
865 fp1 = floatx80_mul(fp0, fp0, status);
866 fp2 = float32_to_floatx80(make_float32(0x3AB60B70),
867 status);
868 fp2 = floatx80_mul(fp2, fp1, status);
869 fp3 = floatx80_mul(float32_to_floatx80(make_float32(0x3C088895),
870 status), fp1,
871 status);
872 fp2 = floatx80_add(fp2, float64_to_floatx80(make_float64(
873 0x3FA5555555554431), status),
874 status);
875 fp3 = floatx80_add(fp3, float64_to_floatx80(make_float64(
876 0x3FC5555555554018), status),
877 status);
878 fp2 = floatx80_mul(fp2, fp1, status);
879 fp3 = floatx80_mul(fp3, fp1, status);
880 fp2 = floatx80_add(fp2, float32_to_floatx80(
881 make_float32(0x3F000000), status),
882 status);
883 fp3 = floatx80_mul(fp3, fp0, status);
884 fp2 = floatx80_mul(fp2, fp1,
885 status);
886 fp0 = floatx80_add(fp0, fp3, status);
887 fp0 = floatx80_add(fp0, fp2, status);
888
889 fp1 = exp_tbl[j];
890 fp0 = floatx80_mul(fp0, fp1, status);
891 fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j], status),
892 status);
893 fp0 = floatx80_add(fp0, fp1,
894 status);
895
896 scale = packFloatx80(0, m, one_sig);
897 if (adjflag) {
898 adjscale = packFloatx80(0, m1, one_sig);
899 fp0 = floatx80_mul(fp0, adjscale, status);
900 }
901
902 status->float_rounding_mode = user_rnd_mode;
903 status->floatx80_rounding_precision = user_rnd_prec;
904
905 a = floatx80_mul(fp0, scale, status);
906
907 float_raise(float_flag_inexact, status);
908
909 return a;
910 } else {
911 if (compact > 0x400CB27C) {
912 status->float_rounding_mode = user_rnd_mode;
913 status->floatx80_rounding_precision = user_rnd_prec;
914 if (aSign) {
915 a = roundAndPackFloatx80(
916 status->floatx80_rounding_precision,
917 0, -0x1000, aSig, 0, status);
918 } else {
919 a = roundAndPackFloatx80(
920 status->floatx80_rounding_precision,
921 0, 0x8000, aSig, 0, status);
922 }
923 float_raise(float_flag_inexact, status);
924
925 return a;
926 } else {
927 fp0 = a;
928 fp1 = a;
929 fp0 = floatx80_mul(fp0, float32_to_floatx80(
930 make_float32(0x42B8AA3B), status),
931 status);
932 adjflag = 1;
933 n = floatx80_to_int32(fp0, status);
934 fp0 = int32_to_floatx80(n, status);
935
936 j = n & 0x3F;
937
938 k = n / 64;
939 if (n < 0 && j) {
940
941
942
943 k--;
944 }
945
946 m1 = k / 2;
947 if (k < 0 && (k & 1)) {
948
949
950
951 m1--;
952 }
953 m = k - m1;
954 m1 += 0x3FFF;
955 m += 0x3FFF;
956
957 goto expcont1;
958 }
959 }
960 } else {
961 status->float_rounding_mode = user_rnd_mode;
962 status->floatx80_rounding_precision = user_rnd_prec;
963
964 a = floatx80_add(a, float32_to_floatx80(make_float32(0x3F800000),
965 status), status);
966
967 float_raise(float_flag_inexact, status);
968
969 return a;
970 }
971}
972
973
974
975
976
977floatx80 floatx80_twotox(floatx80 a, float_status *status)
978{
979 flag aSign;
980 int32_t aExp;
981 uint64_t aSig;
982
983 int8_t user_rnd_mode, user_rnd_prec;
984
985 int32_t compact, n, j, l, m, m1;
986 floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2;
987
988 aSig = extractFloatx80Frac(a);
989 aExp = extractFloatx80Exp(a);
990 aSign = extractFloatx80Sign(a);
991
992 if (aExp == 0x7FFF) {
993 if ((uint64_t) (aSig << 1)) {
994 return propagateFloatx80NaNOneArg(a, status);
995 }
996 if (aSign) {
997 return packFloatx80(0, 0, 0);
998 }
999 return packFloatx80(0, floatx80_infinity.high,
1000 floatx80_infinity.low);
1001 }
1002
1003 if (aExp == 0 && aSig == 0) {
1004 return packFloatx80(0, one_exp, one_sig);
1005 }
1006
1007 user_rnd_mode = status->float_rounding_mode;
1008 user_rnd_prec = status->floatx80_rounding_precision;
1009 status->float_rounding_mode = float_round_nearest_even;
1010 status->floatx80_rounding_precision = 80;
1011
1012 fp0 = a;
1013
1014 compact = floatx80_make_compact(aExp, aSig);
1015
1016 if (compact < 0x3FB98000 || compact > 0x400D80C0) {
1017
1018 if (compact > 0x3FFF8000) {
1019 status->float_rounding_mode = user_rnd_mode;
1020 status->floatx80_rounding_precision = user_rnd_prec;
1021
1022 if (aSign) {
1023 return roundAndPackFloatx80(status->floatx80_rounding_precision,
1024 0, -0x1000, aSig, 0, status);
1025 } else {
1026 return roundAndPackFloatx80(status->floatx80_rounding_precision,
1027 0, 0x8000, aSig, 0, status);
1028 }
1029 } else {
1030 status->float_rounding_mode = user_rnd_mode;
1031 status->floatx80_rounding_precision = user_rnd_prec;
1032
1033 a = floatx80_add(fp0, float32_to_floatx80(
1034 make_float32(0x3F800000), status),
1035 status);
1036
1037 float_raise(float_flag_inexact, status);
1038
1039 return a;
1040 }
1041 } else {
1042 fp1 = fp0;
1043 fp1 = floatx80_mul(fp1, float32_to_floatx80(
1044 make_float32(0x42800000), status),
1045 status);
1046 n = floatx80_to_int32(fp1, status);
1047 fp1 = int32_to_floatx80(n, status);
1048 j = n & 0x3F;
1049 l = n / 64;
1050 if (n < 0 && j) {
1051
1052
1053
1054 l--;
1055 }
1056 m = l / 2;
1057 if (l < 0 && (l & 1)) {
1058
1059
1060
1061 m--;
1062 }
1063 m1 = l - m;
1064 m1 += 0x3FFF;
1065
1066 adjfact = packFloatx80(0, m1, one_sig);
1067 fact1 = exp2_tbl[j];
1068 fact1.high += m;
1069 fact2.high = exp2_tbl2[j] >> 16;
1070 fact2.high += m;
1071 fact2.low = (uint64_t)(exp2_tbl2[j] & 0xFFFF);
1072 fact2.low <<= 48;
1073
1074 fp1 = floatx80_mul(fp1, float32_to_floatx80(
1075 make_float32(0x3C800000), status),
1076 status);
1077 fp0 = floatx80_sub(fp0, fp1, status);
1078 fp2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC));
1079 fp0 = floatx80_mul(fp0, fp2, status);
1080
1081
1082 fp1 = floatx80_mul(fp0, fp0, status);
1083 fp2 = float64_to_floatx80(make_float64(0x3F56C16D6F7BD0B2),
1084 status);
1085 fp3 = float64_to_floatx80(make_float64(0x3F811112302C712C),
1086 status);
1087 fp2 = floatx80_mul(fp2, fp1, status);
1088 fp3 = floatx80_mul(fp3, fp1, status);
1089 fp2 = floatx80_add(fp2, float64_to_floatx80(
1090 make_float64(0x3FA5555555554CC1), status),
1091 status);
1092 fp3 = floatx80_add(fp3, float64_to_floatx80(
1093 make_float64(0x3FC5555555554A54), status),
1094 status);
1095 fp2 = floatx80_mul(fp2, fp1, status);
1096 fp3 = floatx80_mul(fp3, fp1, status);
1097 fp2 = floatx80_add(fp2, float64_to_floatx80(
1098 make_float64(0x3FE0000000000000), status),
1099 status);
1100 fp3 = floatx80_mul(fp3, fp0, status);
1101
1102 fp2 = floatx80_mul(fp2, fp1, status);
1103 fp0 = floatx80_add(fp0, fp3, status);
1104 fp0 = floatx80_add(fp0, fp2, status);
1105
1106 fp0 = floatx80_mul(fp0, fact1, status);
1107 fp0 = floatx80_add(fp0, fact2, status);
1108 fp0 = floatx80_add(fp0, fact1, status);
1109
1110 status->float_rounding_mode = user_rnd_mode;
1111 status->floatx80_rounding_precision = user_rnd_prec;
1112
1113 a = floatx80_mul(fp0, adjfact, status);
1114
1115 float_raise(float_flag_inexact, status);
1116
1117 return a;
1118 }
1119}
1120
1121
1122
1123
1124
1125floatx80 floatx80_tentox(floatx80 a, float_status *status)
1126{
1127 flag aSign;
1128 int32_t aExp;
1129 uint64_t aSig;
1130
1131 int8_t user_rnd_mode, user_rnd_prec;
1132
1133 int32_t compact, n, j, l, m, m1;
1134 floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2;
1135
1136 aSig = extractFloatx80Frac(a);
1137 aExp = extractFloatx80Exp(a);
1138 aSign = extractFloatx80Sign(a);
1139
1140 if (aExp == 0x7FFF) {
1141 if ((uint64_t) (aSig << 1)) {
1142 return propagateFloatx80NaNOneArg(a, status);
1143 }
1144 if (aSign) {
1145 return packFloatx80(0, 0, 0);
1146 }
1147 return packFloatx80(0, floatx80_infinity.high,
1148 floatx80_infinity.low);
1149 }
1150
1151 if (aExp == 0 && aSig == 0) {
1152 return packFloatx80(0, one_exp, one_sig);
1153 }
1154
1155 user_rnd_mode = status->float_rounding_mode;
1156 user_rnd_prec = status->floatx80_rounding_precision;
1157 status->float_rounding_mode = float_round_nearest_even;
1158 status->floatx80_rounding_precision = 80;
1159
1160 fp0 = a;
1161
1162 compact = floatx80_make_compact(aExp, aSig);
1163
1164 if (compact < 0x3FB98000 || compact > 0x400B9B07) {
1165
1166 if (compact > 0x3FFF8000) {
1167 status->float_rounding_mode = user_rnd_mode;
1168 status->floatx80_rounding_precision = user_rnd_prec;
1169
1170 if (aSign) {
1171 return roundAndPackFloatx80(status->floatx80_rounding_precision,
1172 0, -0x1000, aSig, 0, status);
1173 } else {
1174 return roundAndPackFloatx80(status->floatx80_rounding_precision,
1175 0, 0x8000, aSig, 0, status);
1176 }
1177 } else {
1178 status->float_rounding_mode = user_rnd_mode;
1179 status->floatx80_rounding_precision = user_rnd_prec;
1180
1181 a = floatx80_add(fp0, float32_to_floatx80(
1182 make_float32(0x3F800000), status),
1183 status);
1184
1185 float_raise(float_flag_inexact, status);
1186
1187 return a;
1188 }
1189 } else {
1190 fp1 = fp0;
1191 fp1 = floatx80_mul(fp1, float64_to_floatx80(
1192 make_float64(0x406A934F0979A371),
1193 status), status);
1194 n = floatx80_to_int32(fp1, status);
1195 fp1 = int32_to_floatx80(n, status);
1196
1197 j = n & 0x3F;
1198 l = n / 64;
1199 if (n < 0 && j) {
1200
1201
1202
1203 l--;
1204 }
1205 m = l / 2;
1206 if (l < 0 && (l & 1)) {
1207
1208
1209
1210 m--;
1211 }
1212 m1 = l - m;
1213 m1 += 0x3FFF;
1214
1215 adjfact = packFloatx80(0, m1, one_sig);
1216 fact1 = exp2_tbl[j];
1217 fact1.high += m;
1218 fact2.high = exp2_tbl2[j] >> 16;
1219 fact2.high += m;
1220 fact2.low = (uint64_t)(exp2_tbl2[j] & 0xFFFF);
1221 fact2.low <<= 48;
1222
1223 fp2 = fp1;
1224 fp1 = floatx80_mul(fp1, float64_to_floatx80(
1225 make_float64(0x3F734413509F8000), status),
1226 status);
1227 fp3 = packFloatx80(1, 0x3FCD, LIT64(0xC0219DC1DA994FD2));
1228 fp2 = floatx80_mul(fp2, fp3, status);
1229 fp0 = floatx80_sub(fp0, fp1, status);
1230 fp0 = floatx80_sub(fp0, fp2, status);
1231 fp2 = packFloatx80(0, 0x4000, LIT64(0x935D8DDDAAA8AC17));
1232 fp0 = floatx80_mul(fp0, fp2, status);
1233
1234
1235 fp1 = floatx80_mul(fp0, fp0, status);
1236 fp2 = float64_to_floatx80(make_float64(0x3F56C16D6F7BD0B2),
1237 status);
1238 fp3 = float64_to_floatx80(make_float64(0x3F811112302C712C),
1239 status);
1240 fp2 = floatx80_mul(fp2, fp1, status);
1241 fp3 = floatx80_mul(fp3, fp1, status);
1242 fp2 = floatx80_add(fp2, float64_to_floatx80(
1243 make_float64(0x3FA5555555554CC1), status),
1244 status);
1245 fp3 = floatx80_add(fp3, float64_to_floatx80(
1246 make_float64(0x3FC5555555554A54), status),
1247 status);
1248 fp2 = floatx80_mul(fp2, fp1, status);
1249 fp3 = floatx80_mul(fp3, fp1, status);
1250 fp2 = floatx80_add(fp2, float64_to_floatx80(
1251 make_float64(0x3FE0000000000000), status),
1252 status);
1253 fp3 = floatx80_mul(fp3, fp0, status);
1254
1255 fp2 = floatx80_mul(fp2, fp1, status);
1256 fp0 = floatx80_add(fp0, fp3, status);
1257 fp0 = floatx80_add(fp0, fp2, status);
1258
1259 fp0 = floatx80_mul(fp0, fact1, status);
1260 fp0 = floatx80_add(fp0, fact2, status);
1261 fp0 = floatx80_add(fp0, fact1, status);
1262
1263 status->float_rounding_mode = user_rnd_mode;
1264 status->floatx80_rounding_precision = user_rnd_prec;
1265
1266 a = floatx80_mul(fp0, adjfact, status);
1267
1268 float_raise(float_flag_inexact, status);
1269
1270 return a;
1271 }
1272}
1273
1274
1275
1276
1277
1278floatx80 floatx80_tan(floatx80 a, float_status *status)
1279{
1280 flag aSign, xSign;
1281 int32_t aExp, xExp;
1282 uint64_t aSig, xSig;
1283
1284 int8_t user_rnd_mode, user_rnd_prec;
1285
1286 int32_t compact, l, n, j;
1287 floatx80 fp0, fp1, fp2, fp3, fp4, fp5, invtwopi, twopi1, twopi2;
1288 float32 twoto63;
1289 flag endflag;
1290
1291 aSig = extractFloatx80Frac(a);
1292 aExp = extractFloatx80Exp(a);
1293 aSign = extractFloatx80Sign(a);
1294
1295 if (aExp == 0x7FFF) {
1296 if ((uint64_t) (aSig << 1)) {
1297 return propagateFloatx80NaNOneArg(a, status);
1298 }
1299 float_raise(float_flag_invalid, status);
1300 return floatx80_default_nan(status);
1301 }
1302
1303 if (aExp == 0 && aSig == 0) {
1304 return packFloatx80(aSign, 0, 0);
1305 }
1306
1307 user_rnd_mode = status->float_rounding_mode;
1308 user_rnd_prec = status->floatx80_rounding_precision;
1309 status->float_rounding_mode = float_round_nearest_even;
1310 status->floatx80_rounding_precision = 80;
1311
1312 compact = floatx80_make_compact(aExp, aSig);
1313
1314 fp0 = a;
1315
1316 if (compact < 0x3FD78000 || compact > 0x4004BC7E) {
1317
1318 if (compact > 0x3FFF8000) {
1319
1320 fp1 = packFloatx80(0, 0, 0);
1321 if (compact == 0x7FFEFFFF) {
1322 twopi1 = packFloatx80(aSign ^ 1, 0x7FFE,
1323 LIT64(0xC90FDAA200000000));
1324 twopi2 = packFloatx80(aSign ^ 1, 0x7FDC,
1325 LIT64(0x85A308D300000000));
1326 fp0 = floatx80_add(fp0, twopi1, status);
1327 fp1 = fp0;
1328 fp0 = floatx80_add(fp0, twopi2, status);
1329 fp1 = floatx80_sub(fp1, fp0, status);
1330 fp1 = floatx80_add(fp1, twopi2, status);
1331 }
1332 loop:
1333 xSign = extractFloatx80Sign(fp0);
1334 xExp = extractFloatx80Exp(fp0);
1335 xExp -= 0x3FFF;
1336 if (xExp <= 28) {
1337 l = 0;
1338 endflag = 1;
1339 } else {
1340 l = xExp - 27;
1341 endflag = 0;
1342 }
1343 invtwopi = packFloatx80(0, 0x3FFE - l,
1344 LIT64(0xA2F9836E4E44152A));
1345 twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000));
1346 twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000));
1347
1348
1349 twoto63 = packFloat32(xSign, 0xBE, 0);
1350
1351 fp2 = floatx80_mul(fp0, invtwopi, status);
1352 fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status),
1353 status);
1354 fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status),
1355 status);
1356 fp4 = floatx80_mul(twopi1, fp2, status);
1357 fp5 = floatx80_mul(twopi2, fp2, status);
1358 fp3 = floatx80_add(fp4, fp5, status);
1359 fp4 = floatx80_sub(fp4, fp3, status);
1360 fp0 = floatx80_sub(fp0, fp3, status);
1361 fp4 = floatx80_add(fp4, fp5, status);
1362 fp3 = fp0;
1363 fp1 = floatx80_sub(fp1, fp4, status);
1364 fp0 = floatx80_add(fp0, fp1, status);
1365
1366 if (endflag > 0) {
1367 n = floatx80_to_int32(fp2, status);
1368 goto tancont;
1369 }
1370 fp3 = floatx80_sub(fp3, fp0, status);
1371 fp1 = floatx80_add(fp1, fp3, status);
1372 goto loop;
1373 } else {
1374 status->float_rounding_mode = user_rnd_mode;
1375 status->floatx80_rounding_precision = user_rnd_prec;
1376
1377 a = floatx80_move(a, status);
1378
1379 float_raise(float_flag_inexact, status);
1380
1381 return a;
1382 }
1383 } else {
1384 fp1 = floatx80_mul(fp0, float64_to_floatx80(
1385 make_float64(0x3FE45F306DC9C883), status),
1386 status);
1387
1388 n = floatx80_to_int32(fp1, status);
1389 j = 32 + n;
1390
1391 fp0 = floatx80_sub(fp0, pi_tbl[j], status);
1392 fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status),
1393 status);
1394
1395 tancont:
1396 if (n & 1) {
1397
1398 fp1 = fp0;
1399 fp0 = floatx80_mul(fp0, fp0, status);
1400 fp3 = float64_to_floatx80(make_float64(0x3EA0B759F50F8688),
1401 status);
1402 fp2 = float64_to_floatx80(make_float64(0xBEF2BAA5A8924F04),
1403 status);
1404 fp3 = floatx80_mul(fp3, fp0, status);
1405 fp2 = floatx80_mul(fp2, fp0, status);
1406 fp3 = floatx80_add(fp3, float64_to_floatx80(
1407 make_float64(0xBF346F59B39BA65F), status),
1408 status);
1409 fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00));
1410 fp2 = floatx80_add(fp2, fp4, status);
1411 fp3 = floatx80_mul(fp3, fp0, status);
1412 fp2 = floatx80_mul(fp2, fp0, status);
1413 fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1));
1414 fp3 = floatx80_add(fp3, fp4, status);
1415 fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA));
1416 fp2 = floatx80_add(fp2, fp4, status);
1417 fp3 = floatx80_mul(fp3, fp0, status);
1418 fp2 = floatx80_mul(fp2, fp0, status);
1419 fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE));
1420 fp3 = floatx80_add(fp3, fp4, status);
1421 fp2 = floatx80_mul(fp2, fp1, status);
1422 fp0 = floatx80_mul(fp0, fp3, status);
1423 fp1 = floatx80_add(fp1, fp2, status);
1424 fp0 = floatx80_add(fp0, float32_to_floatx80(
1425 make_float32(0x3F800000), status),
1426 status);
1427
1428 xSign = extractFloatx80Sign(fp1);
1429 xExp = extractFloatx80Exp(fp1);
1430 xSig = extractFloatx80Frac(fp1);
1431 xSign ^= 1;
1432 fp1 = packFloatx80(xSign, xExp, xSig);
1433
1434 status->float_rounding_mode = user_rnd_mode;
1435 status->floatx80_rounding_precision = user_rnd_prec;
1436
1437 a = floatx80_div(fp0, fp1, status);
1438
1439 float_raise(float_flag_inexact, status);
1440
1441 return a;
1442 } else {
1443 fp1 = floatx80_mul(fp0, fp0, status);
1444 fp3 = float64_to_floatx80(make_float64(0x3EA0B759F50F8688),
1445 status);
1446 fp2 = float64_to_floatx80(make_float64(0xBEF2BAA5A8924F04),
1447 status);
1448 fp3 = floatx80_mul(fp3, fp1, status);
1449 fp2 = floatx80_mul(fp2, fp1, status);
1450 fp3 = floatx80_add(fp3, float64_to_floatx80(
1451 make_float64(0xBF346F59B39BA65F), status),
1452 status);
1453 fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00));
1454 fp2 = floatx80_add(fp2, fp4, status);
1455 fp3 = floatx80_mul(fp3, fp1, status);
1456 fp2 = floatx80_mul(fp2, fp1, status);
1457 fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1));
1458 fp3 = floatx80_add(fp3, fp4, status);
1459 fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA));
1460 fp2 = floatx80_add(fp2, fp4, status);
1461 fp3 = floatx80_mul(fp3, fp1, status);
1462 fp2 = floatx80_mul(fp2, fp1, status);
1463 fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE));
1464 fp3 = floatx80_add(fp3, fp4, status);
1465 fp2 = floatx80_mul(fp2, fp0, status);
1466 fp1 = floatx80_mul(fp1, fp3, status);
1467 fp0 = floatx80_add(fp0, fp2, status);
1468 fp1 = floatx80_add(fp1, float32_to_floatx80(
1469 make_float32(0x3F800000), status),
1470 status);
1471
1472 status->float_rounding_mode = user_rnd_mode;
1473 status->floatx80_rounding_precision = user_rnd_prec;
1474
1475 a = floatx80_div(fp0, fp1, status);
1476
1477 float_raise(float_flag_inexact, status);
1478
1479 return a;
1480 }
1481 }
1482}
1483
1484
1485
1486
1487
1488floatx80 floatx80_sin(floatx80 a, float_status *status)
1489{
1490 flag aSign, xSign;
1491 int32_t aExp, xExp;
1492 uint64_t aSig, xSig;
1493
1494 int8_t user_rnd_mode, user_rnd_prec;
1495
1496 int32_t compact, l, n, j;
1497 floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
1498 float32 posneg1, twoto63;
1499 flag adjn, endflag;
1500
1501 aSig = extractFloatx80Frac(a);
1502 aExp = extractFloatx80Exp(a);
1503 aSign = extractFloatx80Sign(a);
1504
1505 if (aExp == 0x7FFF) {
1506 if ((uint64_t) (aSig << 1)) {
1507 return propagateFloatx80NaNOneArg(a, status);
1508 }
1509 float_raise(float_flag_invalid, status);
1510 return floatx80_default_nan(status);
1511 }
1512
1513 if (aExp == 0 && aSig == 0) {
1514 return packFloatx80(aSign, 0, 0);
1515 }
1516
1517 adjn = 0;
1518
1519 user_rnd_mode = status->float_rounding_mode;
1520 user_rnd_prec = status->floatx80_rounding_precision;
1521 status->float_rounding_mode = float_round_nearest_even;
1522 status->floatx80_rounding_precision = 80;
1523
1524 compact = floatx80_make_compact(aExp, aSig);
1525
1526 fp0 = a;
1527
1528 if (compact < 0x3FD78000 || compact > 0x4004BC7E) {
1529
1530 if (compact > 0x3FFF8000) {
1531
1532 fp1 = packFloatx80(0, 0, 0);
1533 if (compact == 0x7FFEFFFF) {
1534 twopi1 = packFloatx80(aSign ^ 1, 0x7FFE,
1535 LIT64(0xC90FDAA200000000));
1536 twopi2 = packFloatx80(aSign ^ 1, 0x7FDC,
1537 LIT64(0x85A308D300000000));
1538 fp0 = floatx80_add(fp0, twopi1, status);
1539 fp1 = fp0;
1540 fp0 = floatx80_add(fp0, twopi2, status);
1541 fp1 = floatx80_sub(fp1, fp0, status);
1542 fp1 = floatx80_add(fp1, twopi2, status);
1543 }
1544 loop:
1545 xSign = extractFloatx80Sign(fp0);
1546 xExp = extractFloatx80Exp(fp0);
1547 xExp -= 0x3FFF;
1548 if (xExp <= 28) {
1549 l = 0;
1550 endflag = 1;
1551 } else {
1552 l = xExp - 27;
1553 endflag = 0;
1554 }
1555 invtwopi = packFloatx80(0, 0x3FFE - l,
1556 LIT64(0xA2F9836E4E44152A));
1557 twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000));
1558 twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000));
1559
1560
1561 twoto63 = packFloat32(xSign, 0xBE, 0);
1562
1563 fp2 = floatx80_mul(fp0, invtwopi, status);
1564 fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status),
1565 status);
1566 fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status),
1567 status);
1568 fp4 = floatx80_mul(twopi1, fp2, status);
1569 fp5 = floatx80_mul(twopi2, fp2, status);
1570 fp3 = floatx80_add(fp4, fp5, status);
1571 fp4 = floatx80_sub(fp4, fp3, status);
1572 fp0 = floatx80_sub(fp0, fp3, status);
1573 fp4 = floatx80_add(fp4, fp5, status);
1574 fp3 = fp0;
1575 fp1 = floatx80_sub(fp1, fp4, status);
1576 fp0 = floatx80_add(fp0, fp1, status);
1577
1578 if (endflag > 0) {
1579 n = floatx80_to_int32(fp2, status);
1580 goto sincont;
1581 }
1582 fp3 = floatx80_sub(fp3, fp0, status);
1583 fp1 = floatx80_add(fp1, fp3, status);
1584 goto loop;
1585 } else {
1586
1587 fp0 = float32_to_floatx80(make_float32(0x3F800000),
1588 status);
1589
1590 status->float_rounding_mode = user_rnd_mode;
1591 status->floatx80_rounding_precision = user_rnd_prec;
1592
1593 if (adjn) {
1594
1595 a = floatx80_sub(fp0, float32_to_floatx80(
1596 make_float32(0x00800000), status), status);
1597 } else {
1598
1599 a = floatx80_move(a, status);
1600 }
1601 float_raise(float_flag_inexact, status);
1602
1603 return a;
1604 }
1605 } else {
1606 fp1 = floatx80_mul(fp0, float64_to_floatx80(
1607 make_float64(0x3FE45F306DC9C883), status),
1608 status);
1609
1610 n = floatx80_to_int32(fp1, status);
1611 j = 32 + n;
1612
1613 fp0 = floatx80_sub(fp0, pi_tbl[j], status);
1614 fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status),
1615 status);
1616
1617 sincont:
1618 if ((n + adjn) & 1) {
1619
1620 fp0 = floatx80_mul(fp0, fp0, status);
1621 fp1 = floatx80_mul(fp0, fp0, status);
1622 fp2 = float64_to_floatx80(make_float64(0x3D2AC4D0D6011EE3),
1623 status);
1624 fp3 = float64_to_floatx80(make_float64(0xBDA9396F9F45AC19),
1625 status);
1626
1627 xSign = extractFloatx80Sign(fp0);
1628 xExp = extractFloatx80Exp(fp0);
1629 xSig = extractFloatx80Frac(fp0);
1630
1631 if (((n + adjn) >> 1) & 1) {
1632 xSign ^= 1;
1633 posneg1 = make_float32(0xBF800000);
1634 } else {
1635 xSign ^= 0;
1636 posneg1 = make_float32(0x3F800000);
1637 }
1638
1639 fp2 = floatx80_mul(fp2, fp1, status);
1640 fp3 = floatx80_mul(fp3, fp1, status);
1641 fp2 = floatx80_add(fp2, float64_to_floatx80(
1642 make_float64(0x3E21EED90612C972), status),
1643 status);
1644 fp3 = floatx80_add(fp3, float64_to_floatx80(
1645 make_float64(0xBE927E4FB79D9FCF), status),
1646 status);
1647 fp2 = floatx80_mul(fp2, fp1, status);
1648 fp3 = floatx80_mul(fp3, fp1, status);
1649 fp2 = floatx80_add(fp2, float64_to_floatx80(
1650 make_float64(0x3EFA01A01A01D423), status),
1651 status);
1652 fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438));
1653 fp3 = floatx80_add(fp3, fp4, status);
1654 fp2 = floatx80_mul(fp2, fp1, status);
1655 fp1 = floatx80_mul(fp1, fp3, status);
1656 fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E));
1657 fp2 = floatx80_add(fp2, fp4, status);
1658 fp1 = floatx80_add(fp1, float32_to_floatx80(
1659 make_float32(0xBF000000), status),
1660 status);
1661 fp0 = floatx80_mul(fp0, fp2, status);
1662 fp0 = floatx80_add(fp0, fp1, status);
1663
1664
1665
1666 x = packFloatx80(xSign, xExp, xSig);
1667 fp0 = floatx80_mul(fp0, x, status);
1668
1669 status->float_rounding_mode = user_rnd_mode;
1670 status->floatx80_rounding_precision = user_rnd_prec;
1671
1672 a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status);
1673
1674 float_raise(float_flag_inexact, status);
1675
1676 return a;
1677 } else {
1678
1679 xSign = extractFloatx80Sign(fp0);
1680 xExp = extractFloatx80Exp(fp0);
1681 xSig = extractFloatx80Frac(fp0);
1682
1683 xSign ^= ((n + adjn) >> 1) & 1;
1684
1685 fp0 = floatx80_mul(fp0, fp0, status);
1686 fp1 = floatx80_mul(fp0, fp0, status);
1687 fp3 = float64_to_floatx80(make_float64(0xBD6AAA77CCC994F5),
1688 status);
1689 fp2 = float64_to_floatx80(make_float64(0x3DE612097AAE8DA1),
1690 status);
1691 fp3 = floatx80_mul(fp3, fp1, status);
1692 fp2 = floatx80_mul(fp2, fp1, status);
1693 fp3 = floatx80_add(fp3, float64_to_floatx80(
1694 make_float64(0xBE5AE6452A118AE4), status),
1695 status);
1696 fp2 = floatx80_add(fp2, float64_to_floatx80(
1697 make_float64(0x3EC71DE3A5341531), status),
1698 status);
1699 fp3 = floatx80_mul(fp3, fp1, status);
1700 fp2 = floatx80_mul(fp2, fp1, status);
1701 fp3 = floatx80_add(fp3, float64_to_floatx80(
1702 make_float64(0xBF2A01A01A018B59), status),
1703 status);
1704 fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF));
1705 fp2 = floatx80_add(fp2, fp4, status);
1706 fp1 = floatx80_mul(fp1, fp3, status);
1707 fp2 = floatx80_mul(fp2, fp0, status);
1708 fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99));
1709 fp1 = floatx80_add(fp1, fp4, status);
1710 fp1 = floatx80_add(fp1, fp2,
1711 status);
1712
1713
1714
1715 x = packFloatx80(xSign, xExp, xSig);
1716 fp0 = floatx80_mul(fp0, x, status);
1717 fp0 = floatx80_mul(fp0, fp1, status);
1718
1719 status->float_rounding_mode = user_rnd_mode;
1720 status->floatx80_rounding_precision = user_rnd_prec;
1721
1722 a = floatx80_add(fp0, x, status);
1723
1724 float_raise(float_flag_inexact, status);
1725
1726 return a;
1727 }
1728 }
1729}
1730
1731
1732
1733
1734
1735floatx80 floatx80_cos(floatx80 a, float_status *status)
1736{
1737 flag aSign, xSign;
1738 int32_t aExp, xExp;
1739 uint64_t aSig, xSig;
1740
1741 int8_t user_rnd_mode, user_rnd_prec;
1742
1743 int32_t compact, l, n, j;
1744 floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
1745 float32 posneg1, twoto63;
1746 flag adjn, endflag;
1747
1748 aSig = extractFloatx80Frac(a);
1749 aExp = extractFloatx80Exp(a);
1750 aSign = extractFloatx80Sign(a);
1751
1752 if (aExp == 0x7FFF) {
1753 if ((uint64_t) (aSig << 1)) {
1754 return propagateFloatx80NaNOneArg(a, status);
1755 }
1756 float_raise(float_flag_invalid, status);
1757 return floatx80_default_nan(status);
1758 }
1759
1760 if (aExp == 0 && aSig == 0) {
1761 return packFloatx80(0, one_exp, one_sig);
1762 }
1763
1764 adjn = 1;
1765
1766 user_rnd_mode = status->float_rounding_mode;
1767 user_rnd_prec = status->floatx80_rounding_precision;
1768 status->float_rounding_mode = float_round_nearest_even;
1769 status->floatx80_rounding_precision = 80;
1770
1771 compact = floatx80_make_compact(aExp, aSig);
1772
1773 fp0 = a;
1774
1775 if (compact < 0x3FD78000 || compact > 0x4004BC7E) {
1776
1777 if (compact > 0x3FFF8000) {
1778
1779 fp1 = packFloatx80(0, 0, 0);
1780 if (compact == 0x7FFEFFFF) {
1781 twopi1 = packFloatx80(aSign ^ 1, 0x7FFE,
1782 LIT64(0xC90FDAA200000000));
1783 twopi2 = packFloatx80(aSign ^ 1, 0x7FDC,
1784 LIT64(0x85A308D300000000));
1785 fp0 = floatx80_add(fp0, twopi1, status);
1786 fp1 = fp0;
1787 fp0 = floatx80_add(fp0, twopi2, status);
1788 fp1 = floatx80_sub(fp1, fp0, status);
1789 fp1 = floatx80_add(fp1, twopi2, status);
1790 }
1791 loop:
1792 xSign = extractFloatx80Sign(fp0);
1793 xExp = extractFloatx80Exp(fp0);
1794 xExp -= 0x3FFF;
1795 if (xExp <= 28) {
1796 l = 0;
1797 endflag = 1;
1798 } else {
1799 l = xExp - 27;
1800 endflag = 0;
1801 }
1802 invtwopi = packFloatx80(0, 0x3FFE - l,
1803 LIT64(0xA2F9836E4E44152A));
1804 twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000));
1805 twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000));
1806
1807
1808 twoto63 = packFloat32(xSign, 0xBE, 0);
1809
1810 fp2 = floatx80_mul(fp0, invtwopi, status);
1811 fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status),
1812 status);
1813 fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status),
1814 status);
1815 fp4 = floatx80_mul(twopi1, fp2, status);
1816 fp5 = floatx80_mul(twopi2, fp2, status);
1817 fp3 = floatx80_add(fp4, fp5, status);
1818 fp4 = floatx80_sub(fp4, fp3, status);
1819 fp0 = floatx80_sub(fp0, fp3, status);
1820 fp4 = floatx80_add(fp4, fp5, status);
1821 fp3 = fp0;
1822 fp1 = floatx80_sub(fp1, fp4, status);
1823 fp0 = floatx80_add(fp0, fp1, status);
1824
1825 if (endflag > 0) {
1826 n = floatx80_to_int32(fp2, status);
1827 goto sincont;
1828 }
1829 fp3 = floatx80_sub(fp3, fp0, status);
1830 fp1 = floatx80_add(fp1, fp3, status);
1831 goto loop;
1832 } else {
1833
1834 fp0 = float32_to_floatx80(make_float32(0x3F800000), status);
1835
1836 status->float_rounding_mode = user_rnd_mode;
1837 status->floatx80_rounding_precision = user_rnd_prec;
1838
1839 if (adjn) {
1840
1841 a = floatx80_sub(fp0, float32_to_floatx80(
1842 make_float32(0x00800000), status),
1843 status);
1844 } else {
1845
1846 a = floatx80_move(a, status);
1847 }
1848 float_raise(float_flag_inexact, status);
1849
1850 return a;
1851 }
1852 } else {
1853 fp1 = floatx80_mul(fp0, float64_to_floatx80(
1854 make_float64(0x3FE45F306DC9C883), status),
1855 status);
1856
1857 n = floatx80_to_int32(fp1, status);
1858 j = 32 + n;
1859
1860 fp0 = floatx80_sub(fp0, pi_tbl[j], status);
1861 fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status),
1862 status);
1863
1864 sincont:
1865 if ((n + adjn) & 1) {
1866
1867 fp0 = floatx80_mul(fp0, fp0, status);
1868 fp1 = floatx80_mul(fp0, fp0, status);
1869 fp2 = float64_to_floatx80(make_float64(0x3D2AC4D0D6011EE3),
1870 status);
1871 fp3 = float64_to_floatx80(make_float64(0xBDA9396F9F45AC19),
1872 status);
1873
1874 xSign = extractFloatx80Sign(fp0);
1875 xExp = extractFloatx80Exp(fp0);
1876 xSig = extractFloatx80Frac(fp0);
1877
1878 if (((n + adjn) >> 1) & 1) {
1879 xSign ^= 1;
1880 posneg1 = make_float32(0xBF800000);
1881 } else {
1882 xSign ^= 0;
1883 posneg1 = make_float32(0x3F800000);
1884 }
1885
1886 fp2 = floatx80_mul(fp2, fp1, status);
1887 fp3 = floatx80_mul(fp3, fp1, status);
1888 fp2 = floatx80_add(fp2, float64_to_floatx80(
1889 make_float64(0x3E21EED90612C972), status),
1890 status);
1891 fp3 = floatx80_add(fp3, float64_to_floatx80(
1892 make_float64(0xBE927E4FB79D9FCF), status),
1893 status);
1894 fp2 = floatx80_mul(fp2, fp1, status);
1895 fp3 = floatx80_mul(fp3, fp1, status);
1896 fp2 = floatx80_add(fp2, float64_to_floatx80(
1897 make_float64(0x3EFA01A01A01D423), status),
1898 status);
1899 fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438));
1900 fp3 = floatx80_add(fp3, fp4, status);
1901 fp2 = floatx80_mul(fp2, fp1, status);
1902 fp1 = floatx80_mul(fp1, fp3, status);
1903 fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E));
1904 fp2 = floatx80_add(fp2, fp4, status);
1905 fp1 = floatx80_add(fp1, float32_to_floatx80(
1906 make_float32(0xBF000000), status),
1907 status);
1908 fp0 = floatx80_mul(fp0, fp2, status);
1909 fp0 = floatx80_add(fp0, fp1, status);
1910
1911
1912 x = packFloatx80(xSign, xExp, xSig);
1913 fp0 = floatx80_mul(fp0, x, status);
1914
1915 status->float_rounding_mode = user_rnd_mode;
1916 status->floatx80_rounding_precision = user_rnd_prec;
1917
1918 a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status);
1919
1920 float_raise(float_flag_inexact, status);
1921
1922 return a;
1923 } else {
1924
1925 xSign = extractFloatx80Sign(fp0);
1926 xExp = extractFloatx80Exp(fp0);
1927 xSig = extractFloatx80Frac(fp0);
1928
1929 xSign ^= ((n + adjn) >> 1) & 1;
1930
1931 fp0 = floatx80_mul(fp0, fp0, status);
1932 fp1 = floatx80_mul(fp0, fp0, status);
1933 fp3 = float64_to_floatx80(make_float64(0xBD6AAA77CCC994F5),
1934 status);
1935 fp2 = float64_to_floatx80(make_float64(0x3DE612097AAE8DA1),
1936 status);
1937 fp3 = floatx80_mul(fp3, fp1, status);
1938 fp2 = floatx80_mul(fp2, fp1, status);
1939 fp3 = floatx80_add(fp3, float64_to_floatx80(
1940 make_float64(0xBE5AE6452A118AE4), status),
1941 status);
1942 fp2 = floatx80_add(fp2, float64_to_floatx80(
1943 make_float64(0x3EC71DE3A5341531), status),
1944 status);
1945 fp3 = floatx80_mul(fp3, fp1, status);
1946 fp2 = floatx80_mul(fp2, fp1, status);
1947 fp3 = floatx80_add(fp3, float64_to_floatx80(
1948 make_float64(0xBF2A01A01A018B59), status),
1949 status);
1950 fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF));
1951 fp2 = floatx80_add(fp2, fp4, status);
1952 fp1 = floatx80_mul(fp1, fp3, status);
1953 fp2 = floatx80_mul(fp2, fp0, status);
1954 fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99));
1955 fp1 = floatx80_add(fp1, fp4, status);
1956 fp1 = floatx80_add(fp1, fp2, status);
1957
1958
1959 x = packFloatx80(xSign, xExp, xSig);
1960 fp0 = floatx80_mul(fp0, x, status);
1961 fp0 = floatx80_mul(fp0, fp1, status);
1962
1963 status->float_rounding_mode = user_rnd_mode;
1964 status->floatx80_rounding_precision = user_rnd_prec;
1965
1966 a = floatx80_add(fp0, x, status);
1967
1968 float_raise(float_flag_inexact, status);
1969
1970 return a;
1971 }
1972 }
1973}
1974
1975
1976
1977
1978
1979floatx80 floatx80_atan(floatx80 a, float_status *status)
1980{
1981 flag aSign;
1982 int32_t aExp;
1983 uint64_t aSig;
1984
1985 int8_t user_rnd_mode, user_rnd_prec;
1986
1987 int32_t compact, tbl_index;
1988 floatx80 fp0, fp1, fp2, fp3, xsave;
1989
1990 aSig = extractFloatx80Frac(a);
1991 aExp = extractFloatx80Exp(a);
1992 aSign = extractFloatx80Sign(a);
1993
1994 if (aExp == 0x7FFF) {
1995 if ((uint64_t) (aSig << 1)) {
1996 return propagateFloatx80NaNOneArg(a, status);
1997 }
1998 a = packFloatx80(aSign, piby2_exp, pi_sig);
1999 float_raise(float_flag_inexact, status);
2000 return floatx80_move(a, status);
2001 }
2002
2003 if (aExp == 0 && aSig == 0) {
2004 return packFloatx80(aSign, 0, 0);
2005 }
2006
2007 compact = floatx80_make_compact(aExp, aSig);
2008
2009 user_rnd_mode = status->float_rounding_mode;
2010 user_rnd_prec = status->floatx80_rounding_precision;
2011 status->float_rounding_mode = float_round_nearest_even;
2012 status->floatx80_rounding_precision = 80;
2013
2014 if (compact < 0x3FFB8000 || compact > 0x4002FFFF) {
2015
2016 if (compact > 0x3FFF8000) {
2017 if (compact > 0x40638000) {
2018 fp0 = packFloatx80(aSign, piby2_exp, pi_sig);
2019 fp1 = packFloatx80(aSign, 0x0001, one_sig);
2020
2021 status->float_rounding_mode = user_rnd_mode;
2022 status->floatx80_rounding_precision = user_rnd_prec;
2023
2024 a = floatx80_sub(fp0, fp1, status);
2025
2026 float_raise(float_flag_inexact, status);
2027
2028 return a;
2029 } else {
2030 fp0 = a;
2031 fp1 = packFloatx80(1, one_exp, one_sig);
2032 fp1 = floatx80_div(fp1, fp0, status);
2033 xsave = fp1;
2034 fp0 = floatx80_mul(fp1, fp1, status);
2035 fp1 = floatx80_mul(fp0, fp0, status);
2036 fp3 = float64_to_floatx80(make_float64(0xBFB70BF398539E6A),
2037 status);
2038 fp2 = float64_to_floatx80(make_float64(0x3FBC7187962D1D7D),
2039 status);
2040 fp3 = floatx80_mul(fp3, fp1, status);
2041 fp2 = floatx80_mul(fp2, fp1, status);
2042 fp3 = floatx80_add(fp3, float64_to_floatx80(
2043 make_float64(0xBFC24924827107B8), status),
2044 status);
2045 fp2 = floatx80_add(fp2, float64_to_floatx80(
2046 make_float64(0x3FC999999996263E), status),
2047 status);
2048 fp1 = floatx80_mul(fp1, fp3, status);
2049 fp2 = floatx80_mul(fp2, fp0, status);
2050 fp1 = floatx80_add(fp1, float64_to_floatx80(
2051 make_float64(0xBFD5555555555536), status),
2052 status);
2053 fp0 = floatx80_mul(fp0, xsave, status);
2054
2055 fp1 = floatx80_add(fp1, fp2, status);
2056
2057 fp0 = floatx80_mul(fp0, fp1, status);
2058 fp0 = floatx80_add(fp0, xsave, status);
2059 fp1 = packFloatx80(aSign, piby2_exp, pi_sig);
2060
2061 status->float_rounding_mode = user_rnd_mode;
2062 status->floatx80_rounding_precision = user_rnd_prec;
2063
2064 a = floatx80_add(fp0, fp1, status);
2065
2066 float_raise(float_flag_inexact, status);
2067
2068 return a;
2069 }
2070 } else {
2071 if (compact < 0x3FD78000) {
2072 status->float_rounding_mode = user_rnd_mode;
2073 status->floatx80_rounding_precision = user_rnd_prec;
2074
2075 a = floatx80_move(a, status);
2076
2077 float_raise(float_flag_inexact, status);
2078
2079 return a;
2080 } else {
2081 fp0 = a;
2082 xsave = a;
2083 fp0 = floatx80_mul(fp0, fp0, status);
2084 fp1 = floatx80_mul(fp0, fp0, status);
2085 fp2 = float64_to_floatx80(make_float64(0x3FB344447F876989),
2086 status);
2087 fp3 = float64_to_floatx80(make_float64(0xBFB744EE7FAF45DB),
2088 status);
2089 fp2 = floatx80_mul(fp2, fp1, status);
2090 fp3 = floatx80_mul(fp3, fp1, status);
2091 fp2 = floatx80_add(fp2, float64_to_floatx80(
2092 make_float64(0x3FBC71C646940220), status),
2093 status);
2094 fp3 = floatx80_add(fp3, float64_to_floatx80(
2095 make_float64(0xBFC24924921872F9),
2096 status), status);
2097 fp2 = floatx80_mul(fp2, fp1, status);
2098 fp1 = floatx80_mul(fp1, fp3, status);
2099 fp2 = floatx80_add(fp2, float64_to_floatx80(
2100 make_float64(0x3FC9999999998FA9), status),
2101 status);
2102 fp1 = floatx80_add(fp1, float64_to_floatx80(
2103 make_float64(0xBFD5555555555555), status),
2104 status);
2105 fp2 = floatx80_mul(fp2, fp0, status);
2106 fp0 = floatx80_mul(fp0, xsave, status);
2107
2108 fp1 = floatx80_add(fp1, fp2, status);
2109
2110 fp0 = floatx80_mul(fp0, fp1, status);
2111
2112 status->float_rounding_mode = user_rnd_mode;
2113 status->floatx80_rounding_precision = user_rnd_prec;
2114
2115 a = floatx80_add(fp0, xsave, status);
2116
2117 float_raise(float_flag_inexact, status);
2118
2119 return a;
2120 }
2121 }
2122 } else {
2123 aSig &= LIT64(0xF800000000000000);
2124 aSig |= LIT64(0x0400000000000000);
2125 xsave = packFloatx80(aSign, aExp, aSig);
2126 fp0 = a;
2127 fp1 = a;
2128 fp2 = packFloatx80(0, one_exp, one_sig);
2129 fp1 = floatx80_mul(fp1, xsave, status);
2130 fp0 = floatx80_sub(fp0, xsave, status);
2131 fp1 = floatx80_add(fp1, fp2, status);
2132 fp0 = floatx80_div(fp0, fp1, status);
2133
2134 tbl_index = compact;
2135
2136 tbl_index &= 0x7FFF0000;
2137 tbl_index -= 0x3FFB0000;
2138 tbl_index >>= 1;
2139 tbl_index += compact & 0x00007800;
2140 tbl_index >>= 11;
2141
2142 fp3 = atan_tbl[tbl_index];
2143
2144 fp3.high |= aSign ? 0x8000 : 0;
2145
2146 fp1 = floatx80_mul(fp0, fp0, status);
2147 fp2 = float64_to_floatx80(make_float64(0xBFF6687E314987D8),
2148 status);
2149 fp2 = floatx80_add(fp2, fp1, status);
2150 fp2 = floatx80_mul(fp2, fp1, status);
2151 fp1 = floatx80_mul(fp1, fp0, status);
2152 fp2 = floatx80_add(fp2, float64_to_floatx80(
2153 make_float64(0x4002AC6934A26DB3), status),
2154 status);
2155 fp1 = floatx80_mul(fp1, float64_to_floatx80(
2156 make_float64(0xBFC2476F4E1DA28E), status),
2157 status);
2158 fp1 = floatx80_mul(fp1, fp2, status);
2159 fp0 = floatx80_add(fp0, fp1, status);
2160
2161 status->float_rounding_mode = user_rnd_mode;
2162 status->floatx80_rounding_precision = user_rnd_prec;
2163
2164 a = floatx80_add(fp0, fp3, status);
2165
2166 float_raise(float_flag_inexact, status);
2167
2168 return a;
2169 }
2170}
2171
2172
2173
2174
2175
2176floatx80 floatx80_asin(floatx80 a, float_status *status)
2177{
2178 flag aSign;
2179 int32_t aExp;
2180 uint64_t aSig;
2181
2182 int8_t user_rnd_mode, user_rnd_prec;
2183
2184 int32_t compact;
2185 floatx80 fp0, fp1, fp2, one;
2186
2187 aSig = extractFloatx80Frac(a);
2188 aExp = extractFloatx80Exp(a);
2189 aSign = extractFloatx80Sign(a);
2190
2191 if (aExp == 0x7FFF && (uint64_t) (aSig << 1)) {
2192 return propagateFloatx80NaNOneArg(a, status);
2193 }
2194
2195 if (aExp == 0 && aSig == 0) {
2196 return packFloatx80(aSign, 0, 0);
2197 }
2198
2199 compact = floatx80_make_compact(aExp, aSig);
2200
2201 if (compact >= 0x3FFF8000) {
2202 if (aExp == one_exp && aSig == one_sig) {
2203 float_raise(float_flag_inexact, status);
2204 a = packFloatx80(aSign, piby2_exp, pi_sig);
2205 return floatx80_move(a, status);
2206 } else {
2207 float_raise(float_flag_invalid, status);
2208 return floatx80_default_nan(status);
2209 }
2210
2211 }
2212
2213 user_rnd_mode = status->float_rounding_mode;
2214 user_rnd_prec = status->floatx80_rounding_precision;
2215 status->float_rounding_mode = float_round_nearest_even;
2216 status->floatx80_rounding_precision = 80;
2217
2218 one = packFloatx80(0, one_exp, one_sig);
2219 fp0 = a;
2220
2221 fp1 = floatx80_sub(one, fp0, status);
2222 fp2 = floatx80_add(one, fp0, status);
2223 fp1 = floatx80_mul(fp2, fp1, status);
2224 fp1 = floatx80_sqrt(fp1, status);
2225 fp0 = floatx80_div(fp0, fp1, status);
2226
2227 status->float_rounding_mode = user_rnd_mode;
2228 status->floatx80_rounding_precision = user_rnd_prec;
2229
2230 a = floatx80_atan(fp0, status);
2231
2232 float_raise(float_flag_inexact, status);
2233
2234 return a;
2235}
2236
2237
2238
2239
2240
2241floatx80 floatx80_acos(floatx80 a, float_status *status)
2242{
2243 flag aSign;
2244 int32_t aExp;
2245 uint64_t aSig;
2246
2247 int8_t user_rnd_mode, user_rnd_prec;
2248
2249 int32_t compact;
2250 floatx80 fp0, fp1, one;
2251
2252 aSig = extractFloatx80Frac(a);
2253 aExp = extractFloatx80Exp(a);
2254 aSign = extractFloatx80Sign(a);
2255
2256 if (aExp == 0x7FFF && (uint64_t) (aSig << 1)) {
2257 return propagateFloatx80NaNOneArg(a, status);
2258 }
2259 if (aExp == 0 && aSig == 0) {
2260 float_raise(float_flag_inexact, status);
2261 return roundAndPackFloatx80(status->floatx80_rounding_precision, 0,
2262 piby2_exp, pi_sig, 0, status);
2263 }
2264
2265 compact = floatx80_make_compact(aExp, aSig);
2266
2267 if (compact >= 0x3FFF8000) {
2268 if (aExp == one_exp && aSig == one_sig) {
2269 if (aSign) {
2270 a = packFloatx80(0, pi_exp, pi_sig);
2271 float_raise(float_flag_inexact, status);
2272 return floatx80_move(a, status);
2273 } else {
2274 return packFloatx80(0, 0, 0);
2275 }
2276 } else {
2277 float_raise(float_flag_invalid, status);
2278 return floatx80_default_nan(status);
2279 }
2280 }
2281
2282 user_rnd_mode = status->float_rounding_mode;
2283 user_rnd_prec = status->floatx80_rounding_precision;
2284 status->float_rounding_mode = float_round_nearest_even;
2285 status->floatx80_rounding_precision = 80;
2286
2287 one = packFloatx80(0, one_exp, one_sig);
2288 fp0 = a;
2289
2290 fp1 = floatx80_add(one, fp0, status);
2291 fp0 = floatx80_sub(one, fp0, status);
2292 fp0 = floatx80_div(fp0, fp1, status);
2293 fp0 = floatx80_sqrt(fp0, status);
2294 fp0 = floatx80_atan(fp0, status);
2295
2296 status->float_rounding_mode = user_rnd_mode;
2297 status->floatx80_rounding_precision = user_rnd_prec;
2298
2299 a = floatx80_add(fp0, fp0, status);
2300
2301 float_raise(float_flag_inexact, status);
2302
2303 return a;
2304}
2305
2306
2307
2308
2309
2310floatx80 floatx80_atanh(floatx80 a, float_status *status)
2311{
2312 flag aSign;
2313 int32_t aExp;
2314 uint64_t aSig;
2315
2316 int8_t user_rnd_mode, user_rnd_prec;
2317
2318 int32_t compact;
2319 floatx80 fp0, fp1, fp2, one;
2320
2321 aSig = extractFloatx80Frac(a);
2322 aExp = extractFloatx80Exp(a);
2323 aSign = extractFloatx80Sign(a);
2324
2325 if (aExp == 0x7FFF && (uint64_t) (aSig << 1)) {
2326 return propagateFloatx80NaNOneArg(a, status);
2327 }
2328
2329 if (aExp == 0 && aSig == 0) {
2330 return packFloatx80(aSign, 0, 0);
2331 }
2332
2333 compact = floatx80_make_compact(aExp, aSig);
2334
2335 if (compact >= 0x3FFF8000) {
2336 if (aExp == one_exp && aSig == one_sig) {
2337 float_raise(float_flag_divbyzero, status);
2338 return packFloatx80(aSign, floatx80_infinity.high,
2339 floatx80_infinity.low);
2340 } else {
2341 float_raise(float_flag_invalid, status);
2342 return floatx80_default_nan(status);
2343 }
2344 }
2345
2346 user_rnd_mode = status->float_rounding_mode;
2347 user_rnd_prec = status->floatx80_rounding_precision;
2348 status->float_rounding_mode = float_round_nearest_even;
2349 status->floatx80_rounding_precision = 80;
2350
2351 one = packFloatx80(0, one_exp, one_sig);
2352 fp2 = packFloatx80(aSign, 0x3FFE, one_sig);
2353 fp0 = packFloatx80(0, aExp, aSig);
2354 fp1 = packFloatx80(1, aExp, aSig);
2355 fp0 = floatx80_add(fp0, fp0, status);
2356 fp1 = floatx80_add(fp1, one, status);
2357 fp0 = floatx80_div(fp0, fp1, status);
2358 fp0 = floatx80_lognp1(fp0, status);
2359
2360 status->float_rounding_mode = user_rnd_mode;
2361 status->floatx80_rounding_precision = user_rnd_prec;
2362
2363 a = floatx80_mul(fp0, fp2,
2364 status);
2365
2366 float_raise(float_flag_inexact, status);
2367
2368 return a;
2369}
2370
2371
2372
2373
2374
2375floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
2376{
2377 flag aSign;
2378 int32_t aExp;
2379 uint64_t aSig;
2380
2381 int8_t user_rnd_mode, user_rnd_prec;
2382
2383 int32_t compact, n, j, m, m1;
2384 floatx80 fp0, fp1, fp2, fp3, l2, sc, onebysc;
2385
2386 aSig = extractFloatx80Frac(a);
2387 aExp = extractFloatx80Exp(a);
2388 aSign = extractFloatx80Sign(a);
2389
2390 if (aExp == 0x7FFF) {
2391 if ((uint64_t) (aSig << 1)) {
2392 return propagateFloatx80NaNOneArg(a, status);
2393 }
2394 if (aSign) {
2395 return packFloatx80(aSign, one_exp, one_sig);
2396 }
2397 return packFloatx80(0, floatx80_infinity.high,
2398 floatx80_infinity.low);
2399 }
2400
2401 if (aExp == 0 && aSig == 0) {
2402 return packFloatx80(aSign, 0, 0);
2403 }
2404
2405 user_rnd_mode = status->float_rounding_mode;
2406 user_rnd_prec = status->floatx80_rounding_precision;
2407 status->float_rounding_mode = float_round_nearest_even;
2408 status->floatx80_rounding_precision = 80;
2409
2410 if (aExp >= 0x3FFD) {
2411 compact = floatx80_make_compact(aExp, aSig);
2412
2413 if (compact <= 0x4004C215) {
2414 fp0 = a;
2415 fp1 = a;
2416 fp0 = floatx80_mul(fp0, float32_to_floatx80(
2417 make_float32(0x42B8AA3B), status),
2418 status);
2419 n = floatx80_to_int32(fp0, status);
2420 fp0 = int32_to_floatx80(n, status);
2421
2422 j = n & 0x3F;
2423 m = n / 64;
2424 if (n < 0 && j) {
2425
2426
2427
2428 m--;
2429 }
2430 m1 = -m;
2431
2432
2433
2434 fp2 = fp0;
2435 fp0 = floatx80_mul(fp0, float32_to_floatx80(
2436 make_float32(0xBC317218), status),
2437 status);
2438 l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6));
2439 fp2 = floatx80_mul(fp2, l2, status);
2440 fp0 = floatx80_add(fp0, fp1, status);
2441 fp0 = floatx80_add(fp0, fp2, status);
2442
2443 fp1 = floatx80_mul(fp0, fp0, status);
2444 fp2 = float32_to_floatx80(make_float32(0x3950097B),
2445 status);
2446 fp2 = floatx80_mul(fp2, fp1, status);
2447 fp3 = floatx80_mul(float32_to_floatx80(make_float32(0x3AB60B6A),
2448 status), fp1, status);
2449 fp2 = floatx80_add(fp2, float64_to_floatx80(
2450 make_float64(0x3F81111111174385), status),
2451 status);
2452 fp3 = floatx80_add(fp3, float64_to_floatx80(
2453 make_float64(0x3FA5555555554F5A), status),
2454 status);
2455 fp2 = floatx80_mul(fp2, fp1, status);
2456 fp3 = floatx80_mul(fp3, fp1, status);
2457 fp2 = floatx80_add(fp2, float64_to_floatx80(
2458 make_float64(0x3FC5555555555555), status),
2459 status);
2460 fp3 = floatx80_add(fp3, float32_to_floatx80(
2461 make_float32(0x3F000000), status),
2462 status);
2463 fp2 = floatx80_mul(fp2, fp1,
2464 status);
2465 fp1 = floatx80_mul(fp1, fp3,
2466 status);
2467 fp2 = floatx80_mul(fp2, fp0,
2468 status);
2469 fp0 = floatx80_add(fp0, fp1,
2470 status);
2471 fp0 = floatx80_add(fp0, fp2, status);
2472
2473 fp0 = floatx80_mul(fp0, exp_tbl[j],
2474 status);
2475
2476 if (m >= 64) {
2477 fp1 = float32_to_floatx80(exp_tbl2[j], status);
2478 onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig);
2479 fp1 = floatx80_add(fp1, onebysc, status);
2480 fp0 = floatx80_add(fp0, fp1, status);
2481 fp0 = floatx80_add(fp0, exp_tbl[j], status);
2482 } else if (m < -3) {
2483 fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j],
2484 status), status);
2485 fp0 = floatx80_add(fp0, exp_tbl[j], status);
2486 onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig);
2487 fp0 = floatx80_add(fp0, onebysc, status);
2488 } else {
2489 fp1 = exp_tbl[j];
2490 fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j],
2491 status), status);
2492 onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig);
2493 fp1 = floatx80_add(fp1, onebysc, status);
2494 fp0 = floatx80_add(fp0, fp1, status);
2495 }
2496
2497 sc = packFloatx80(0, m + 0x3FFF, one_sig);
2498
2499 status->float_rounding_mode = user_rnd_mode;
2500 status->floatx80_rounding_precision = user_rnd_prec;
2501
2502 a = floatx80_mul(fp0, sc, status);
2503
2504 float_raise(float_flag_inexact, status);
2505
2506 return a;
2507 } else {
2508 if (aSign) {
2509 fp0 = float32_to_floatx80(make_float32(0xBF800000),
2510 status);
2511
2512 status->float_rounding_mode = user_rnd_mode;
2513 status->floatx80_rounding_precision = user_rnd_prec;
2514
2515 a = floatx80_add(fp0, float32_to_floatx80(
2516 make_float32(0x00800000), status),
2517 status);
2518
2519 float_raise(float_flag_inexact, status);
2520
2521 return a;
2522 } else {
2523 status->float_rounding_mode = user_rnd_mode;
2524 status->floatx80_rounding_precision = user_rnd_prec;
2525
2526 return floatx80_etox(a, status);
2527 }
2528 }
2529 } else {
2530 if (aExp >= 0x3FBE) {
2531 fp0 = a;
2532 fp0 = floatx80_mul(fp0, fp0, status);
2533 fp1 = float32_to_floatx80(make_float32(0x2F30CAA8),
2534 status);
2535 fp1 = floatx80_mul(fp1, fp0, status);
2536 fp2 = float32_to_floatx80(make_float32(0x310F8290),
2537 status);
2538 fp1 = floatx80_add(fp1, float32_to_floatx80(
2539 make_float32(0x32D73220), status),
2540 status);
2541 fp2 = floatx80_mul(fp2, fp0, status);
2542 fp1 = floatx80_mul(fp1, fp0, status);
2543 fp2 = floatx80_add(fp2, float32_to_floatx80(
2544 make_float32(0x3493F281), status),
2545 status);
2546 fp1 = floatx80_add(fp1, float64_to_floatx80(
2547 make_float64(0x3EC71DE3A5774682), status),
2548 status);
2549 fp2 = floatx80_mul(fp2, fp0, status);
2550 fp1 = floatx80_mul(fp1, fp0, status);
2551 fp2 = floatx80_add(fp2, float64_to_floatx80(
2552 make_float64(0x3EFA01A019D7CB68), status),
2553 status);
2554 fp1 = floatx80_add(fp1, float64_to_floatx80(
2555 make_float64(0x3F2A01A01A019DF3), status),
2556 status);
2557 fp2 = floatx80_mul(fp2, fp0, status);
2558 fp1 = floatx80_mul(fp1, fp0, status);
2559 fp2 = floatx80_add(fp2, float64_to_floatx80(
2560 make_float64(0x3F56C16C16C170E2), status),
2561 status);
2562 fp1 = floatx80_add(fp1, float64_to_floatx80(
2563 make_float64(0x3F81111111111111), status),
2564 status);
2565 fp2 = floatx80_mul(fp2, fp0, status);
2566 fp1 = floatx80_mul(fp1, fp0, status);
2567 fp2 = floatx80_add(fp2, float64_to_floatx80(
2568 make_float64(0x3FA5555555555555), status),
2569 status);
2570 fp3 = packFloatx80(0, 0x3FFC, LIT64(0xAAAAAAAAAAAAAAAB));
2571 fp1 = floatx80_add(fp1, fp3, status);
2572 fp2 = floatx80_mul(fp2, fp0, status);
2573 fp1 = floatx80_mul(fp1, fp0, status);
2574
2575 fp2 = floatx80_mul(fp2, fp0, status);
2576 fp1 = floatx80_mul(fp1, a, status);
2577
2578 fp0 = floatx80_mul(fp0, float32_to_floatx80(
2579 make_float32(0x3F000000), status),
2580 status);
2581 fp1 = floatx80_add(fp1, fp2, status);
2582 fp0 = floatx80_add(fp0, fp1, status);
2583
2584 status->float_rounding_mode = user_rnd_mode;
2585 status->floatx80_rounding_precision = user_rnd_prec;
2586
2587 a = floatx80_add(fp0, a, status);
2588
2589 float_raise(float_flag_inexact, status);
2590
2591 return a;
2592 } else {
2593 sc = packFloatx80(1, 1, one_sig);
2594 fp0 = a;
2595
2596 if (aExp < 0x0033) {
2597 fp0 = floatx80_mul(fp0, float64_to_floatx80(
2598 make_float64(0x48B0000000000000), status),
2599 status);
2600 fp0 = floatx80_add(fp0, sc, status);
2601
2602 status->float_rounding_mode = user_rnd_mode;
2603 status->floatx80_rounding_precision = user_rnd_prec;
2604
2605 a = floatx80_mul(fp0, float64_to_floatx80(
2606 make_float64(0x3730000000000000), status),
2607 status);
2608 } else {
2609 status->float_rounding_mode = user_rnd_mode;
2610 status->floatx80_rounding_precision = user_rnd_prec;
2611
2612 a = floatx80_add(fp0, sc, status);
2613 }
2614
2615 float_raise(float_flag_inexact, status);
2616
2617 return a;
2618 }
2619 }
2620}
2621
2622
2623
2624
2625
2626floatx80 floatx80_tanh(floatx80 a, float_status *status)
2627{
2628 flag aSign, vSign;
2629 int32_t aExp, vExp;
2630 uint64_t aSig, vSig;
2631
2632 int8_t user_rnd_mode, user_rnd_prec;
2633
2634 int32_t compact;
2635 floatx80 fp0, fp1;
2636 uint32_t sign;
2637
2638 aSig = extractFloatx80Frac(a);
2639 aExp = extractFloatx80Exp(a);
2640 aSign = extractFloatx80Sign(a);
2641
2642 if (aExp == 0x7FFF) {
2643 if ((uint64_t) (aSig << 1)) {
2644 return propagateFloatx80NaNOneArg(a, status);
2645 }
2646 return packFloatx80(aSign, one_exp, one_sig);
2647 }
2648
2649 if (aExp == 0 && aSig == 0) {
2650 return packFloatx80(aSign, 0, 0);
2651 }
2652
2653 user_rnd_mode = status->float_rounding_mode;
2654 user_rnd_prec = status->floatx80_rounding_precision;
2655 status->float_rounding_mode = float_round_nearest_even;
2656 status->floatx80_rounding_precision = 80;
2657
2658 compact = floatx80_make_compact(aExp, aSig);
2659
2660 if (compact < 0x3FD78000 || compact > 0x3FFFDDCE) {
2661
2662 if (compact < 0x3FFF8000) {
2663
2664 status->float_rounding_mode = user_rnd_mode;
2665 status->floatx80_rounding_precision = user_rnd_prec;
2666
2667 a = floatx80_move(a, status);
2668
2669 float_raise(float_flag_inexact, status);
2670
2671 return a;
2672 } else {
2673 if (compact > 0x40048AA1) {
2674
2675 sign = 0x3F800000;
2676 sign |= aSign ? 0x80000000 : 0x00000000;
2677 fp0 = float32_to_floatx80(make_float32(sign), status);
2678 sign &= 0x80000000;
2679 sign ^= 0x80800000;
2680
2681 status->float_rounding_mode = user_rnd_mode;
2682 status->floatx80_rounding_precision = user_rnd_prec;
2683
2684 a = floatx80_add(fp0, float32_to_floatx80(make_float32(sign),
2685 status), status);
2686
2687 float_raise(float_flag_inexact, status);
2688
2689 return a;
2690 } else {
2691 fp0 = packFloatx80(0, aExp + 1, aSig);
2692 fp0 = floatx80_etox(fp0, status);
2693 fp0 = floatx80_add(fp0, float32_to_floatx80(
2694 make_float32(0x3F800000),
2695 status), status);
2696 sign = aSign ? 0x80000000 : 0x00000000;
2697 fp1 = floatx80_div(float32_to_floatx80(make_float32(
2698 sign ^ 0xC0000000), status), fp0,
2699 status);
2700 fp0 = float32_to_floatx80(make_float32(sign | 0x3F800000),
2701 status);
2702
2703 status->float_rounding_mode = user_rnd_mode;
2704 status->floatx80_rounding_precision = user_rnd_prec;
2705
2706 a = floatx80_add(fp1, fp0, status);
2707
2708 float_raise(float_flag_inexact, status);
2709
2710 return a;
2711 }
2712 }
2713 } else {
2714 fp0 = packFloatx80(0, aExp + 1, aSig);
2715 fp0 = floatx80_etoxm1(fp0, status);
2716 fp1 = floatx80_add(fp0, float32_to_floatx80(make_float32(0x40000000),
2717 status),
2718 status);
2719
2720 vSign = extractFloatx80Sign(fp1);
2721 vExp = extractFloatx80Exp(fp1);
2722 vSig = extractFloatx80Frac(fp1);
2723
2724 fp1 = packFloatx80(vSign ^ aSign, vExp, vSig);
2725
2726 status->float_rounding_mode = user_rnd_mode;
2727 status->floatx80_rounding_precision = user_rnd_prec;
2728
2729 a = floatx80_div(fp0, fp1, status);
2730
2731 float_raise(float_flag_inexact, status);
2732
2733 return a;
2734 }
2735}
2736
2737
2738
2739
2740
2741floatx80 floatx80_sinh(floatx80 a, float_status *status)
2742{
2743 flag aSign;
2744 int32_t aExp;
2745 uint64_t aSig;
2746
2747 int8_t user_rnd_mode, user_rnd_prec;
2748
2749 int32_t compact;
2750 floatx80 fp0, fp1, fp2;
2751 float32 fact;
2752
2753 aSig = extractFloatx80Frac(a);
2754 aExp = extractFloatx80Exp(a);
2755 aSign = extractFloatx80Sign(a);
2756
2757 if (aExp == 0x7FFF) {
2758 if ((uint64_t) (aSig << 1)) {
2759 return propagateFloatx80NaNOneArg(a, status);
2760 }
2761 return packFloatx80(aSign, floatx80_infinity.high,
2762 floatx80_infinity.low);
2763 }
2764
2765 if (aExp == 0 && aSig == 0) {
2766 return packFloatx80(aSign, 0, 0);
2767 }
2768
2769 user_rnd_mode = status->float_rounding_mode;
2770 user_rnd_prec = status->floatx80_rounding_precision;
2771 status->float_rounding_mode = float_round_nearest_even;
2772 status->floatx80_rounding_precision = 80;
2773
2774 compact = floatx80_make_compact(aExp, aSig);
2775
2776 if (compact > 0x400CB167) {
2777
2778 if (compact > 0x400CB2B3) {
2779 status->float_rounding_mode = user_rnd_mode;
2780 status->floatx80_rounding_precision = user_rnd_prec;
2781
2782 return roundAndPackFloatx80(status->floatx80_rounding_precision,
2783 aSign, 0x8000, aSig, 0, status);
2784 } else {
2785 fp0 = floatx80_abs(a);
2786 fp0 = floatx80_sub(fp0, float64_to_floatx80(
2787 make_float64(0x40C62D38D3D64634), status),
2788 status);
2789 fp0 = floatx80_sub(fp0, float64_to_floatx80(
2790 make_float64(0x3D6F90AEB1E75CC7), status),
2791 status);
2792 fp0 = floatx80_etox(fp0, status);
2793 fp2 = packFloatx80(aSign, 0x7FFB, one_sig);
2794
2795 status->float_rounding_mode = user_rnd_mode;
2796 status->floatx80_rounding_precision = user_rnd_prec;
2797
2798 a = floatx80_mul(fp0, fp2, status);
2799
2800 float_raise(float_flag_inexact, status);
2801
2802 return a;
2803 }
2804 } else {
2805 fp0 = floatx80_abs(a);
2806 fp0 = floatx80_etoxm1(fp0, status);
2807 fp1 = floatx80_add(fp0, float32_to_floatx80(make_float32(0x3F800000),
2808 status), status);
2809 fp2 = fp0;
2810 fp0 = floatx80_div(fp0, fp1, status);
2811 fp0 = floatx80_add(fp0, fp2, status);
2812
2813 fact = packFloat32(aSign, 0x7E, 0);
2814
2815 status->float_rounding_mode = user_rnd_mode;
2816 status->floatx80_rounding_precision = user_rnd_prec;
2817
2818 a = floatx80_mul(fp0, float32_to_floatx80(fact, status), status);
2819
2820 float_raise(float_flag_inexact, status);
2821
2822 return a;
2823 }
2824}
2825
2826
2827
2828
2829
2830floatx80 floatx80_cosh(floatx80 a, float_status *status)
2831{
2832 int32_t aExp;
2833 uint64_t aSig;
2834
2835 int8_t user_rnd_mode, user_rnd_prec;
2836
2837 int32_t compact;
2838 floatx80 fp0, fp1;
2839
2840 aSig = extractFloatx80Frac(a);
2841 aExp = extractFloatx80Exp(a);
2842
2843 if (aExp == 0x7FFF) {
2844 if ((uint64_t) (aSig << 1)) {
2845 return propagateFloatx80NaNOneArg(a, status);
2846 }
2847 return packFloatx80(0, floatx80_infinity.high,
2848 floatx80_infinity.low);
2849 }
2850
2851 if (aExp == 0 && aSig == 0) {
2852 return packFloatx80(0, one_exp, one_sig);
2853 }
2854
2855 user_rnd_mode = status->float_rounding_mode;
2856 user_rnd_prec = status->floatx80_rounding_precision;
2857 status->float_rounding_mode = float_round_nearest_even;
2858 status->floatx80_rounding_precision = 80;
2859
2860 compact = floatx80_make_compact(aExp, aSig);
2861
2862 if (compact > 0x400CB167) {
2863 if (compact > 0x400CB2B3) {
2864 status->float_rounding_mode = user_rnd_mode;
2865 status->floatx80_rounding_precision = user_rnd_prec;
2866 return roundAndPackFloatx80(status->floatx80_rounding_precision, 0,
2867 0x8000, one_sig, 0, status);
2868 } else {
2869 fp0 = packFloatx80(0, aExp, aSig);
2870 fp0 = floatx80_sub(fp0, float64_to_floatx80(
2871 make_float64(0x40C62D38D3D64634), status),
2872 status);
2873 fp0 = floatx80_sub(fp0, float64_to_floatx80(
2874 make_float64(0x3D6F90AEB1E75CC7), status),
2875 status);
2876 fp0 = floatx80_etox(fp0, status);
2877 fp1 = packFloatx80(0, 0x7FFB, one_sig);
2878
2879 status->float_rounding_mode = user_rnd_mode;
2880 status->floatx80_rounding_precision = user_rnd_prec;
2881
2882 a = floatx80_mul(fp0, fp1, status);
2883
2884 float_raise(float_flag_inexact, status);
2885
2886 return a;
2887 }
2888 }
2889
2890 fp0 = packFloatx80(0, aExp, aSig);
2891 fp0 = floatx80_etox(fp0, status);
2892 fp0 = floatx80_mul(fp0, float32_to_floatx80(make_float32(0x3F000000),
2893 status), status);
2894 fp1 = float32_to_floatx80(make_float32(0x3E800000), status);
2895 fp1 = floatx80_div(fp1, fp0, status);
2896
2897 status->float_rounding_mode = user_rnd_mode;
2898 status->floatx80_rounding_precision = user_rnd_prec;
2899
2900 a = floatx80_add(fp0, fp1, status);
2901
2902 float_raise(float_flag_inexact, status);
2903
2904 return a;
2905}
2906