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

unix.superglobalmegacorp.com

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