|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * MC68881 emulation
5: *
6: * Conversion routines for hosts knowing floating point format.
7: *
8: * Copyright 1996 Herman ten Brugge
9: * Modified 2005 Peter Keunecke
10: */
11:
12: #ifndef FPP_H
13: #define FPP_H
14:
15: #include <softfloat.h>
16:
17:
18: #define FPCR_ROUNDING_MODE 0x00000030
19: #define FPCR_ROUND_NEAR 0x00000000
20: #define FPCR_ROUND_ZERO 0x00000010
21: #define FPCR_ROUND_MINF 0x00000020
22: #define FPCR_ROUND_PINF 0x00000030
23:
24: #define FPCR_ROUNDING_PRECISION 0x000000c0
25: #define FPCR_PRECISION_SINGLE 0x00000040
26: #define FPCR_PRECISION_DOUBLE 0x00000080
27: #define FPCR_PRECISION_EXTENDED 0x00000000
28:
29: extern uae_u32 fpp_get_fpsr (void);
30:
31:
32: /* Functions for setting host/library modes and getting status */
33: STATIC_INLINE void set_fp_mode(uae_u32 mode_control)
34: {
35: float_detect_tininess = float_tininess_before_rounding;
36:
37: switch(mode_control & FPCR_ROUNDING_PRECISION) {
38: case FPCR_PRECISION_SINGLE: // single
39: floatx80_rounding_precision = 32;
40: break;
41: case FPCR_PRECISION_DOUBLE: // double
42: floatx80_rounding_precision = 64;
43: break;
44: case FPCR_PRECISION_EXTENDED: // extended
45: floatx80_rounding_precision = 80;
46: break;
47: default: // double
48: floatx80_rounding_precision = 64;
49: break;
50: }
51:
52: switch(mode_control & FPCR_ROUNDING_MODE) {
53: case FPCR_ROUND_NEAR: // to neareset
54: float_rounding_mode = float_round_nearest_even;
55: break;
56: case FPCR_ROUND_ZERO: // to zero
57: float_rounding_mode = float_round_to_zero;
58: break;
59: case FPCR_ROUND_MINF: // to minus
60: float_rounding_mode = float_round_down;
61: break;
62: case FPCR_ROUND_PINF: // to plus
63: float_rounding_mode = float_round_up;
64: break;
65: }
66: }
67: STATIC_INLINE void get_fp_status(uae_u32 *status)
68: {
69: if (float_exception_flags & float_flag_signaling)
70: *status |= 0x4000;
71: if (float_exception_flags & float_flag_invalid)
72: *status |= 0x2000;
73: if (float_exception_flags & float_flag_overflow)
74: *status |= 0x1000;
75: if (float_exception_flags & float_flag_underflow)
76: *status |= 0x0800;
77: if (float_exception_flags & float_flag_divbyzero)
78: *status |= 0x0400;
79: if (float_exception_flags & float_flag_inexact)
80: *status |= 0x0200;
81: if (float_exception_flags & float_flag_decimal)
82: *status |= 0x0100;
83: }
84: STATIC_INLINE void clear_fp_status(void)
85: {
86: float_exception_flags = 0;
87: }
88:
89: /* Helper functions */
90: STATIC_INLINE const char *fp_print(fptype *fx)
91: {
92: static char fs[32];
93: bool n, u, d;
94: fptype x;
95: int32 len;
96: int8 save_exception_flags;
97:
98: n = floatx80_is_negative(*fx);
99: u = floatx80_is_unnormal(*fx);
100: d = floatx80_is_denormal(*fx);
101:
102: if (floatx80_is_infinity(*fx)) {
103: sprintf(fs, "%c%s", n?'-':'+', "inf");
104: } else if (floatx80_is_signaling_nan(*fx)) {
105: sprintf(fs, "%c%s", n?'-':'+', "snan");
106: } else if (floatx80_is_nan(*fx)) {
107: sprintf(fs, "%c%s", n?'-':'+', "nan");
108: } else {
109: len = 17;
110: save_exception_flags = float_exception_flags;
111: float_exception_flags = 0;
112: x = floatx80_to_floatdecimal(*fx, &len);
113:
114: sprintf(fs, "%c%01lld.%016llde%c%04d%s%s", n?'-':'+',
115: x.low/LIT64(10000000000000000), x.low%LIT64(10000000000000000),
116: (x.high&0x4000)?'-':'+', x.high&0x3FFF, d?"D":u?"U":"",
117: (float_exception_flags&float_flag_inexact)?"~":"");
118:
119: float_exception_flags = save_exception_flags;
120: }
121:
122: return fs;
123: }
124:
125: /* Functions for detecting float type */
126: STATIC_INLINE bool fp_is_snan(fptype *fp)
127: {
128: return floatx80_is_signaling_nan(*fp) != 0;
129: }
130: STATIC_INLINE void fp_unset_snan(fptype *fp)
131: {
132: fp->low |= LIT64(0x4000000000000000);
133: }
134: STATIC_INLINE bool fp_is_nan (fptype *fp)
135: {
136: return floatx80_is_nan(*fp) != 0;
137: }
138: STATIC_INLINE bool fp_is_infinity (fptype *fp)
139: {
140: return floatx80_is_infinity(*fp) != 0;
141: }
142: STATIC_INLINE bool fp_is_zero(fptype *fp)
143: {
144: return floatx80_is_zero(*fp) != 0;
145: }
146: STATIC_INLINE bool fp_is_neg(fptype *fp)
147: {
148: return floatx80_is_negative(*fp) != 0;
149: }
150: STATIC_INLINE bool fp_is_denormal(fptype *fp)
151: {
152: return floatx80_is_denormal(*fp) != 0;
153: }
154: STATIC_INLINE bool fp_is_unnormal(fptype *fp)
155: {
156: return floatx80_is_unnormal(*fp) != 0;
157: }
158:
159: /* Function for normalizing unnormals */
160: STATIC_INLINE void fp_normalize(fptype *fp)
161: {
162: *fp = floatx80_normalize(*fp);
163: }
164:
165: /* Functions for converting between float formats */
166: STATIC_INLINE void to_single(fptype *fp, uae_u32 wrd1)
167: {
168: float32 f = wrd1;
169: *fp = float32_to_floatx80_allowunnormal(f);
170: }
171: STATIC_INLINE uae_u32 from_single(fptype *fp)
172: {
173: float32 f = floatx80_to_float32(*fp);
174: return f;
175: }
176:
177: STATIC_INLINE void to_double(fptype *fp, uae_u32 wrd1, uae_u32 wrd2)
178: {
179: float64 f = ((float64)wrd1 << 32) | wrd2;
180: *fp = float64_to_floatx80_allowunnormal(f);
181: }
182: STATIC_INLINE void from_double(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2)
183: {
184: float64 f = floatx80_to_float64(*fp);
185: *wrd1 = f >> 32;
186: *wrd2 = (uae_u32)f;
187: }
188:
189: STATIC_INLINE void to_exten(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
190: {
191: fp->high = (uae_u16)(wrd1 >> 16);
192: fp->low = ((uae_u64)wrd2 << 32) | wrd3;
193: }
194: STATIC_INLINE void from_exten(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3)
195: {
196: floatx80 f = floatx80_to_floatx80(*fp);
197: *wrd1 = (uae_u32)(f.high << 16);
198: *wrd2 = f.low >> 32;
199: *wrd3 = (uae_u32)f.low;
200: }
201: STATIC_INLINE void to_exten_fmovem(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
202: {
203: fp->high = (uae_u16)(wrd1 >> 16);
204: fp->low = ((uae_u64)wrd2 << 32) | wrd3;
205: }
206: STATIC_INLINE void from_exten_fmovem(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3)
207: {
208: *wrd1 = (uae_u32)(fp->high << 16);
209: *wrd2 = fp->low >> 32;
210: *wrd3 = (uae_u32)fp->low;
211: }
212:
213: STATIC_INLINE uae_s64 to_int(fptype *src, int size)
214: {
215: switch (size) {
216: case 0: return floatx80_to_int8(*src);
217: case 1: return floatx80_to_int16(*src);
218: case 2: return floatx80_to_int32(*src);
219: default: return 0;
220: }
221: }
222: STATIC_INLINE fptype from_int(uae_s32 src)
223: {
224: return int32_to_floatx80(src);
225: }
226:
227: STATIC_INLINE void to_pack(fptype *fp, uae_u32 *wrd)
228: {
229: floatx80 f;
230: int i;
231: uae_s32 exp;
232: uae_s64 mant;
233: uae_u32 pack_exp, pack_int, pack_se, pack_sm;
234: uae_u64 pack_frac;
235:
236: if (((wrd[0] >> 16) & 0x7fff) == 0x7fff) {
237: // infinity has extended exponent and all 0 packed fraction
238: // nans are copies bit by bit
239: to_exten(fp, wrd[0], wrd[1], wrd[2]);
240: return;
241: }
242: if (!(wrd[0] & 0xf) && !wrd[1] && !wrd[2]) {
243: // exponent is not cared about, if mantissa is zero
244: wrd[0] &= 0x80000000;
245: to_exten(fp, wrd[0], wrd[1], wrd[2]);
246: return;
247: }
248:
249: pack_exp = (wrd[0] >> 16) & 0xFFF; // packed exponent
250: pack_int = wrd[0] & 0xF; // packed integer part
251: pack_frac = ((uae_u64)wrd[1] << 32) | wrd[2]; // packed fraction
252: pack_se = (wrd[0] >> 30) & 1; // sign of packed exponent
253: pack_sm = (wrd[0] >> 31) & 1; // sign of packed significand
254:
255: exp = 0;
256:
257: for (i = 0; i < 3; i++) {
258: exp *= 10;
259: exp += (pack_exp >> (8 - i * 4)) & 0xF;
260: }
261:
262: if (pack_se) {
263: exp = -exp;
264: }
265:
266: exp -= 16;
267:
268: if (exp < 0) {
269: exp = -exp;
270: pack_se = 1;
271: }
272:
273: mant = pack_int;
274:
275: for (i = 0; i < 16; i++) {
276: mant *= 10;
277: mant += (pack_frac >> (60 - i * 4)) & 0xF;
278: }
279:
280: f.high = exp & 0x3FFF;
281: f.high |= pack_se ? 0x4000 : 0;
282: f.high |= pack_sm ? 0x8000 : 0;
283: f.low = mant;
284:
285: *fp = floatdecimal_to_floatx80(f);
286: }
287: STATIC_INLINE void from_pack(fptype *fp, uae_u32 *wrd, uae_s32 kfactor)
288: {
289: floatx80 f = floatx80_to_floatdecimal(*fp, &kfactor);
290:
291: uae_u32 pack_exp, pack_exp4, pack_int, pack_se, pack_sm;
292: uae_u64 pack_frac;
293:
294: uae_u32 exponent;
295: uae_u64 significand;
296:
297: uae_s32 len;
298: uae_u64 digit;
299:
300: if ((f.high & 0x7FFF) == 0x7FFF) {
301: wrd[0] = (uae_u32)(f.high << 16);
302: wrd[1] = f.low >> 32;
303: wrd[2] = (uae_u32)f.low;
304: } else {
305: exponent = f.high & 0x3FFF;
306: significand = f.low;
307:
308: pack_int = 0;
309: pack_frac = 0;
310: len = kfactor; // SoftFloat saved len to kfactor variable
311: while (len > 0) {
312: len--;
313: digit = significand % 10;
314: significand /= 10;
315: if (len == 0) {
316: pack_int = digit;
317: } else {
318: pack_frac |= digit << (64 - len * 4);
319: }
320: }
321:
322: pack_exp = 0;
323: pack_exp4 = 0;
324: len = 4;
325: while (len > 0) {
326: len--;
327: digit = exponent % 10;
328: exponent /= 10;
329: if (len == 0) {
330: pack_exp4 = digit;
331: } else {
332: pack_exp |= digit << (12 - len * 4);
333: }
334: }
335:
336: pack_se = f.high & 0x4000;
337: pack_sm = f.high & 0x8000;
338:
339: wrd[0] = pack_exp << 16;
340: wrd[0] |= pack_exp4 << 12;
341: wrd[0] |= pack_int;
342: wrd[0] |= pack_se ? 0x40000000 : 0;
343: wrd[0] |= pack_sm ? 0x80000000 : 0;
344:
345: wrd[1] = pack_frac >> 32;
346: wrd[2] = pack_frac & 0xffffffff;
347: }
348: }
349:
350: /* Functions for returning exception state data */
351: STATIC_INLINE fptype fp_get_internal_overflow(void)
352: {
353: return getFloatInternalOverflow();
354: }
355: STATIC_INLINE fptype fp_get_internal_underflow(void)
356: {
357: return getFloatInternalUnderflow();
358: }
359: STATIC_INLINE fptype fp_get_internal_round_all(void)
360: {
361: return getFloatInternalRoundedAll();
362: }
363: STATIC_INLINE fptype fp_get_internal_round(void)
364: {
365: return getFloatInternalRoundedSome();
366: }
367: STATIC_INLINE fptype fp_get_internal_round_exten(void)
368: {
369: return getFloatInternalFloatx80();
370: }
371: STATIC_INLINE fptype fp_get_internal(void)
372: {
373: return getFloatInternalUnrounded();
374: }
375: STATIC_INLINE uae_u32 fp_get_internal_grs(void)
376: {
377: return (uae_u32)getFloatInternalGRS();
378: }
379:
380: /* Function for denormalizing */
381: STATIC_INLINE void fp_denormalize(fptype *fp, int esign)
382: {
383: *fp = floatx80_denormalize(*fp, esign);
384: }
385:
386: /* Functions for rounding */
387:
388: // round to float with extended precision exponent
389: STATIC_INLINE void fp_round32(fptype *fp)
390: {
391: *fp = floatx80_round32(*fp);
392: }
393:
394: // round to double with extended precision exponent
395: STATIC_INLINE void fp_round64(fptype *fp)
396: {
397: *fp = floatx80_round64(*fp);
398: }
399:
400: // round to float
401: STATIC_INLINE void fp_round_single(fptype *fp)
402: {
403: *fp = floatx80_round_to_float32(*fp);
404: }
405:
406: // round to double
407: STATIC_INLINE void fp_round_double(fptype *fp)
408: {
409: *fp = floatx80_round_to_float64(*fp);
410: }
411:
412: // round to selected precision
413: STATIC_INLINE void fp_round(fptype *a)
414: {
415: switch(floatx80_rounding_precision) {
416: case 32:
417: *a = floatx80_round_to_float32(*a);
418: break;
419: case 64:
420: *a = floatx80_round_to_float64(*a);
421: break;
422: default:
423: break;
424: }
425: }
426:
427: /* Arithmetic functions */
428: STATIC_INLINE void fp_move(fptype *a, fptype *b)
429: {
430: *a = floatx80_move(*b);
431: }
432: STATIC_INLINE void fp_int(fptype *a, fptype *b)
433: {
434: *a = floatx80_round_to_int(*b);
435: }
436: STATIC_INLINE void fp_intrz(fptype *a, fptype *b)
437: {
438: *a = floatx80_round_to_int_toward_zero(*b);
439: }
440: STATIC_INLINE void fp_sqrt(fptype *a, fptype *b)
441: {
442: *a = floatx80_sqrt(*b);
443: }
444: STATIC_INLINE void fp_abs(fptype *a, fptype *b)
445: {
446: *a = floatx80_abs(*b);
447: }
448: STATIC_INLINE void fp_neg(fptype *a, fptype *b)
449: {
450: *a = floatx80_neg(*b);
451: }
452: STATIC_INLINE void fp_getexp(fptype *a, fptype *b)
453: {
454: *a = floatx80_getexp(*b);
455: }
456: STATIC_INLINE void fp_getman(fptype *a, fptype *b)
457: {
458: *a = floatx80_getman(*b);
459: }
460: STATIC_INLINE void fp_div(fptype *a, fptype *b)
461: {
462: *a = floatx80_div(*a, *b);
463: }
464: STATIC_INLINE void fp_mod(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s)
465: {
466: *a = floatx80_mod(*a, *b, q, s);
467: }
468: STATIC_INLINE void fp_add(fptype *a, fptype *b)
469: {
470: *a = floatx80_add(*a, *b);
471: }
472: STATIC_INLINE void fp_mul(fptype *a, fptype *b)
473: {
474: *a = floatx80_mul(*a, *b);
475: }
476: STATIC_INLINE void fp_sgldiv(fptype *a, fptype *b)
477: {
478: *a = floatx80_sgldiv(*a, *b);
479: }
480: STATIC_INLINE void fp_rem(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s)
481: {
482: *a = floatx80_rem(*a, *b, q, s);
483: }
484: STATIC_INLINE void fp_scale(fptype *a, fptype *b)
485: {
486: *a = floatx80_scale(*a, *b);
487: }
488: STATIC_INLINE void fp_sglmul(fptype *a, fptype *b)
489: {
490: *a = floatx80_sglmul(*a, *b);
491: }
492: STATIC_INLINE void fp_sub(fptype *a, fptype *b)
493: {
494: *a = floatx80_sub(*a, *b);
495: }
496: STATIC_INLINE void fp_cmp(fptype *a, fptype *b)
497: {
498: *a = floatx80_cmp(*a, *b);
499: }
500: STATIC_INLINE void fp_tst(fptype *a, fptype *b)
501: {
502: *a = floatx80_tst(*b);
503: }
504:
505: STATIC_INLINE void fp_sinh(fptype *a, fptype *b)
506: {
507: *a = floatx80_sinh(*b);
508: }
509: STATIC_INLINE void fp_lognp1(fptype *a, fptype *b)
510: {
511: *a = floatx80_lognp1(*b);
512: }
513: STATIC_INLINE void fp_etoxm1(fptype *a, fptype *b)
514: {
515: *a = floatx80_etoxm1(*b);
516: }
517: STATIC_INLINE void fp_tanh(fptype *a, fptype *b)
518: {
519: *a = floatx80_tanh(*b);
520: }
521: STATIC_INLINE void fp_atan(fptype *a, fptype *b)
522: {
523: *a = floatx80_atan(*b);
524: }
525: STATIC_INLINE void fp_asin(fptype *a, fptype *b)
526: {
527: *a = floatx80_asin(*b);
528: }
529: STATIC_INLINE void fp_atanh(fptype *a, fptype *b)
530: {
531: *a = floatx80_atanh(*b);
532: }
533: STATIC_INLINE void fp_sin(fptype *a, fptype *b)
534: {
535: *a = floatx80_sin(*b);
536: }
537: STATIC_INLINE void fp_tan(fptype *a, fptype *b)
538: {
539: *a = floatx80_tan(*b);
540: }
541: STATIC_INLINE void fp_etox(fptype *a, fptype *b)
542: {
543: *a = floatx80_etox(*b);
544: }
545: STATIC_INLINE void fp_twotox(fptype *a, fptype *b)
546: {
547: *a = floatx80_twotox(*b);
548: }
549: STATIC_INLINE void fp_tentox(fptype *a, fptype *b)
550: {
551: *a = floatx80_tentox(*b);
552: }
553: STATIC_INLINE void fp_logn(fptype *a, fptype *b)
554: {
555: *a = floatx80_logn(*b);
556: }
557: STATIC_INLINE void fp_log10(fptype *a, fptype *b)
558: {
559: *a = floatx80_log10(*b);
560: }
561: STATIC_INLINE void fp_log2(fptype *a, fptype *b)
562: {
563: *a = floatx80_log2(*b);
564: }
565: STATIC_INLINE void fp_cosh(fptype *a, fptype *b)
566: {
567: *a = floatx80_cosh(*b);
568: }
569: STATIC_INLINE void fp_acos(fptype *a, fptype *b)
570: {
571: *a = floatx80_acos(*b);
572: }
573: STATIC_INLINE void fp_cos(fptype *a, fptype *b)
574: {
575: *a = floatx80_cos(*b);
576: }
577:
578: /* Functions with fixed precision */
579: STATIC_INLINE void fp_move_single(fptype *a, fptype *b)
580: {
581: int8 oldprec = floatx80_rounding_precision;
582: floatx80_rounding_precision = 32;
583: *a = floatx80_move(*b);
584: floatx80_rounding_precision = oldprec;
585: }
586: STATIC_INLINE void fp_abs_single(fptype *a, fptype *b)
587: {
588: int8 oldprec = floatx80_rounding_precision;
589: floatx80_rounding_precision = 32;
590: *a = floatx80_abs(*b);
591: floatx80_rounding_precision = oldprec;
592: }
593: STATIC_INLINE void fp_neg_single(fptype *a, fptype *b)
594: {
595: int8 oldprec = floatx80_rounding_precision;
596: floatx80_rounding_precision = 32;
597: *a = floatx80_neg(*b);
598: floatx80_rounding_precision = oldprec;
599: }
600: STATIC_INLINE void fp_add_single(fptype *a, fptype *b)
601: {
602: int8 oldprec = floatx80_rounding_precision;
603: floatx80_rounding_precision = 32;
604: *a = floatx80_add(*a, *b);
605: floatx80_rounding_precision = oldprec;
606: }
607: STATIC_INLINE void fp_sub_single(fptype *a, fptype *b)
608: {
609: int8 oldprec = floatx80_rounding_precision;
610: floatx80_rounding_precision = 32;
611: *a = floatx80_sub(*a, *b);
612: floatx80_rounding_precision = oldprec;
613: }
614: STATIC_INLINE void fp_mul_single(fptype *a, fptype *b)
615: {
616: int8 oldprec = floatx80_rounding_precision;
617: floatx80_rounding_precision = 32;
618: *a = floatx80_mul(*a, *b);
619: floatx80_rounding_precision = oldprec;
620: }
621: STATIC_INLINE void fp_div_single(fptype *a, fptype *b)
622: {
623: int8 oldprec = floatx80_rounding_precision;
624: floatx80_rounding_precision = 32;
625: *a = floatx80_div(*a, *b);
626: floatx80_rounding_precision = oldprec;
627: }
628: STATIC_INLINE void fp_sqrt_single(fptype *a, fptype *b)
629: {
630: int8 oldprec = floatx80_rounding_precision;
631: floatx80_rounding_precision = 32;
632: *a = floatx80_sqrt(*b);
633: floatx80_rounding_precision = oldprec;
634: }
635: STATIC_INLINE void fp_move_double(fptype *a, fptype *b)
636: {
637: int8 oldprec = floatx80_rounding_precision;
638: floatx80_rounding_precision = 64;
639: *a = floatx80_move(*b);
640: floatx80_rounding_precision = oldprec;
641: }
642: STATIC_INLINE void fp_abs_double(fptype *a, fptype *b)
643: {
644: int8 oldprec = floatx80_rounding_precision;
645: floatx80_rounding_precision = 64;
646: *a = floatx80_abs(*b);
647: floatx80_rounding_precision = oldprec;
648: }
649: STATIC_INLINE void fp_neg_double(fptype *a, fptype *b)
650: {
651: int8 oldprec = floatx80_rounding_precision;
652: floatx80_rounding_precision = 64;
653: *a = floatx80_neg(*b);
654: floatx80_rounding_precision = oldprec;
655: }
656: STATIC_INLINE void fp_add_double(fptype *a, fptype *b)
657: {
658: int8 oldprec = floatx80_rounding_precision;
659: floatx80_rounding_precision = 64;
660: *a = floatx80_add(*a, *b);
661: floatx80_rounding_precision = oldprec;
662: }
663: STATIC_INLINE void fp_sub_double(fptype *a, fptype *b)
664: {
665: int8 oldprec = floatx80_rounding_precision;
666: floatx80_rounding_precision = 64;
667: *a = floatx80_sub(*a, *b);
668: floatx80_rounding_precision = oldprec;
669: }
670: STATIC_INLINE void fp_mul_double(fptype *a, fptype *b)
671: {
672: int8 oldprec = floatx80_rounding_precision;
673: floatx80_rounding_precision = 64;
674: *a = floatx80_mul(*a, *b);
675: floatx80_rounding_precision = oldprec;
676: }
677: STATIC_INLINE void fp_div_double(fptype *a, fptype *b)
678: {
679: int8 oldprec = floatx80_rounding_precision;
680: floatx80_rounding_precision = 64;
681: *a = floatx80_div(*a, *b);
682: floatx80_rounding_precision = oldprec;
683: }
684: STATIC_INLINE void fp_sqrt_double(fptype *a, fptype *b)
685: {
686: int8 oldprec = floatx80_rounding_precision;
687: floatx80_rounding_precision = 64;
688: *a = floatx80_sqrt(*b);
689: floatx80_rounding_precision = oldprec;
690: }
691:
692:
693:
694: #if 0 /* Old fallback functions disabled */
695: static const long double twoto32 = 4294967296.0;
696:
697: STATIC_INLINE void to_native(long double *fp, fptype fpx)
698: {
699: int expon;
700: long double frac;
701:
702: expon = fpx.high & 0x7fff;
703:
704: if (floatx80_is_zero(fpx)) {
705: *fp = floatx80_is_negative(fpx) ? -0.0 : +0.0;
706: return;
707: }
708: if (floatx80_is_nan(fpx)) {
709: *fp = sqrtl(-1);
710: return;
711: }
712: if (floatx80_is_infinity(fpx)) {
713: *fp = floatx80_is_negative(fpx) ? logl(0.0) : (1.0/0.0);
714: return;
715: }
716:
717: frac = (long double)fpx.low / (long double)(twoto32 * 2147483648.0);
718: if (floatx80_is_negative(fpx))
719: frac = -frac;
720: *fp = ldexpl (frac, expon - 16383);
721: }
722: STATIC_INLINE void from_native(long double fp, fptype *fpx)
723: {
724: int expon;
725: long double frac;
726:
727: if (signbit(fp))
728: fpx->high = 0x8000;
729: else
730: fpx->high = 0x0000;
731:
732: if (isnan(fp)) {
733: fpx->high |= 0x7fff;
734: fpx->low = LIT64(0xffffffffffffffff);
735: return;
736: }
737: if (isinf(fp)) {
738: fpx->high |= 0x7fff;
739: fpx->low = LIT64(0x0000000000000000);
740: return;
741: }
742: if (fp == 0.0) {
743: fpx->low = LIT64(0x0000000000000000);
744: return;
745: }
746: if (fp < 0.0)
747: fp = -fp;
748:
749: frac = frexpl (fp, &expon);
750: frac += 0.5 / (twoto32 * twoto32);
751: if (frac >= 1.0) {
752: frac /= 2.0;
753: expon++;
754: }
755: fpx->high |= (expon + 16383 - 1) & 0x7fff;
756: fpx->low = (bits64)(frac * (long double)(twoto32 * twoto32));
757:
758: while (!(fpx->low & LIT64( 0x8000000000000000))) {
759: if (fpx->high == 0) {
760: break;
761: }
762: fpx->low <<= 1;
763: fpx->high--;
764: }
765: }
766:
767: STATIC_INLINE void fp_sinhf(fptype *a, fptype *b)
768: {
769: flag e = 0;
770: floatx80_sinh_check(*a, &e);
771: if (e) return;
772: long double fp;
773: to_native(&fp, *b);
774: fp = sinhl(fp);
775: from_native(fp, a);
776: fp_round(a);
777: }
778: STATIC_INLINE void fp_lognp1f(fptype *a, fptype *b)
779: {
780: flag e = 0;
781: floatx80_lognp1_check(*a, &e);
782: if (e) return;
783: long double fp;
784: to_native(&fp, *b);
785: fp = log1pl(fp);
786: from_native(fp, a);
787: fp_round(a);
788: }
789: STATIC_INLINE void fp_etoxm1f(fptype *a, fptype *b)
790: {
791: flag e = 0;
792: floatx80_etoxm1_check(*a, &e);
793: if (e) return;
794: long double fp;
795: to_native(&fp, *b);
796: fp = expm1l(fp);
797: from_native(fp, a);
798: fp_round(a);
799: }
800: STATIC_INLINE void fp_tanhf(fptype *a, fptype *b)
801: {
802: flag e = 0;
803: floatx80_tanh_check(*a, &e);
804: if (e) return;
805: long double fp;
806: to_native(&fp, *b);
807: fp = tanhl(fp);
808: from_native(fp, a);
809: fp_round(a);
810: }
811: STATIC_INLINE void fp_atanf(fptype *a, fptype *b)
812: {
813: flag e = 0;
814: floatx80_atan_check(*a, &e);
815: if (e) return;
816: long double fp;
817: to_native(&fp, *b);
818: fp = atanl(fp);
819: from_native(fp, a);
820: fp_round(a);
821: }
822: STATIC_INLINE void fp_asinf(fptype *a, fptype *b)
823: {
824: flag e = 0;
825: floatx80_asin_check(*a, &e);
826: if (e) return;
827: long double fp;
828: to_native(&fp, *b);
829: fp = asinl(fp);
830: from_native(fp, a);
831: fp_round(a);
832: }
833: STATIC_INLINE void fp_atanhf(fptype *a, fptype *b)
834: {
835: flag e = 0;
836: floatx80_atanh_check(*a, &e);
837: if (e) return;
838: long double fp;
839: to_native(&fp, *b);
840: fp = atanhl(fp);
841: from_native(fp, a);
842: fp_round(a);
843: }
844: STATIC_INLINE void fp_sinf(fptype *a, fptype *b)
845: {
846: flag e = 0;
847: floatx80_sin_check(*a, &e);
848: if (e) return;
849: long double fp;
850: to_native(&fp, *b);
851: fp = sinl(fp);
852: from_native(fp, a);
853: fp_round(a);
854: }
855: STATIC_INLINE void fp_tanf(fptype *a, fptype *b)
856: {
857: flag e = 0;
858: floatx80_tan_check(*a, &e);
859: if (e) return;
860: long double fp;
861: to_native(&fp, *b);
862: fp = tanl(fp);
863: from_native(fp, a);
864: fp_round(a);
865: }
866: STATIC_INLINE void fp_etoxf(fptype *a, fptype *b)
867: {
868: flag e = 0;
869: floatx80_etox_check(*a, &e);
870: if (e) return;
871: long double fp;
872: to_native(&fp, *b);
873: fp = expl(fp);
874: from_native(fp, a);
875: fp_round(a);
876: }
877: STATIC_INLINE void fp_twotoxf(fptype *a, fptype *b)
878: {
879: flag e = 0;
880: floatx80_twotox_check(*a, &e);
881: if (e) return;
882: long double fp;
883: to_native(&fp, *b);
884: fp = powl(2.0, fp);
885: from_native(fp, a);
886: fp_round(a);
887: }
888: STATIC_INLINE void fp_tentoxf(fptype *a, fptype *b)
889: {
890: flag e = 0;
891: floatx80_tentox_check(*a, &e);
892: if (e) return;
893: long double fp;
894: to_native(&fp, *b);
895: fp = powl(10.0, fp);
896: from_native(fp, a);
897: fp_round(a);
898: }
899: STATIC_INLINE void fp_lognf(fptype *a, fptype *b)
900: {
901: flag e = 0;
902: floatx80_logn_check(*a, &e);
903: if (e) return;
904: long double fp;
905: to_native(&fp, *b);
906: fp = logl(fp);
907: from_native(fp, a);
908: fp_round(a);
909: }
910: STATIC_INLINE void fp_log10f(fptype *a, fptype *b)
911: {
912: flag e = 0;
913: floatx80_log10_check(*a, &e);
914: if (e) return;
915: long double fp;
916: to_native(&fp, *b);
917: fp = log10l(fp);
918: from_native(fp, a);
919: fp_round(a);
920: }
921: STATIC_INLINE void fp_log2f(fptype *a, fptype *b)
922: {
923: flag e = 0;
924: floatx80_log2_check(*a, &e);
925: if (e) return;
926: long double fp;
927: to_native(&fp, *b);
928: fp = log2l(fp);
929: from_native(fp, a);
930: fp_round(a);
931: }
932: STATIC_INLINE void fp_coshf(fptype *a, fptype *b)
933: {
934: flag e = 0;
935: floatx80_cosh_check(*a, &e);
936: if (e) return;
937: long double fp;
938: to_native(&fp, *b);
939: fp = coshl(fp);
940: from_native(fp, a);
941: fp_round(a);
942: }
943: STATIC_INLINE void fp_acosf(fptype *a, fptype *b)
944: {
945: flag e = 0;
946: floatx80_acos_check(*a, &e);
947: if (e) return;
948: long double fp;
949: to_native(&fp, *b);
950: fp = acosl(fp);
951: from_native(fp, a);
952: fp_round(a);
953: }
954: STATIC_INLINE void fp_cosf(fptype *a, fptype *b)
955: {
956: flag e = 0;
957: floatx80_cos_check(*a, &e);
958: if (e) return;
959: long double fp;
960: to_native(&fp, *b);
961: fp = cosl(fp);
962: from_native(fp, a);
963: fp_round(a);
964: }
965: #endif
966:
967: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.