Annotation of previous/src/cpu/fpp-softfloat.h, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.