|
|
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: #define __USE_ISOC9X /* We might be able to pick up a NaN */ ! 16: ! 17: #include <math.h> ! 18: #include <float.h> ! 19: #include <fenv.h> ! 20: ! 21: //#pragma STDC FENV_ACCESS on ! 22: ! 23: #define USE_HOST_ROUNDING ! 24: ! 25: #define FPCR_ROUNDING_MODE 0x00000030 ! 26: #define FPCR_ROUND_NEAR 0x00000000 ! 27: #define FPCR_ROUND_ZERO 0x00000010 ! 28: #define FPCR_ROUND_MINF 0x00000020 ! 29: #define FPCR_ROUND_PINF 0x00000030 ! 30: ! 31: #define FPCR_ROUNDING_PRECISION 0x000000c0 ! 32: #define FPCR_PRECISION_SINGLE 0x00000040 ! 33: #define FPCR_PRECISION_DOUBLE 0x00000080 ! 34: #define FPCR_PRECISION_EXTENDED 0x00000000 ! 35: ! 36: extern uae_u32 fpp_get_fpsr (void); ! 37: extern void fpsr_set_exception(uae_u32 exception); ! 38: ! 39: static int fp_rnd_prec = 80; ! 40: ! 41: /* Functions for setting host/library modes and getting status */ ! 42: STATIC_INLINE void init_fp_mode(void) { ! 43: ! 44: } ! 45: STATIC_INLINE void set_fp_mode(uae_u32 mode_control) ! 46: { ! 47: switch(mode_control & FPCR_ROUNDING_PRECISION) { ! 48: case FPCR_PRECISION_EXTENDED: // X ! 49: fp_rnd_prec = 80; ! 50: break; ! 51: case FPCR_PRECISION_SINGLE: // S ! 52: fp_rnd_prec = 32; ! 53: break; ! 54: case FPCR_PRECISION_DOUBLE: // D ! 55: default: // undefined ! 56: fp_rnd_prec = 64; ! 57: break; ! 58: } ! 59: #ifdef USE_HOST_ROUNDING ! 60: switch(mode_control & FPCR_ROUNDING_MODE) { ! 61: case FPCR_ROUND_NEAR: // to neareset ! 62: fesetround(FE_TONEAREST); ! 63: break; ! 64: case FPCR_ROUND_ZERO: // to zero ! 65: fesetround(FE_TOWARDZERO); ! 66: break; ! 67: case FPCR_ROUND_MINF: // to minus ! 68: fesetround(FE_DOWNWARD); ! 69: break; ! 70: case FPCR_ROUND_PINF: // to plus ! 71: fesetround(FE_UPWARD); ! 72: break; ! 73: } ! 74: return; ! 75: #endif ! 76: } ! 77: STATIC_INLINE void get_fp_status(uae_u32 *status) ! 78: { ! 79: int exp_flags = fetestexcept(FE_ALL_EXCEPT); ! 80: if (exp_flags) { ! 81: if (exp_flags & FE_INEXACT) ! 82: *status |= 0x0200; ! 83: if (exp_flags & FE_DIVBYZERO) ! 84: *status |= 0x0400; ! 85: if (exp_flags & FE_UNDERFLOW) ! 86: *status |= 0x0800; ! 87: if (exp_flags & FE_OVERFLOW) ! 88: *status |= 0x1000; ! 89: if (exp_flags & FE_INVALID) ! 90: *status |= 0x2000; ! 91: } ! 92: /* FIXME: how to detect SNAN? */ ! 93: } ! 94: STATIC_INLINE void clear_fp_status(void) ! 95: { ! 96: feclearexcept (FE_ALL_EXCEPT); ! 97: } ! 98: ! 99: /* Helper functions */ ! 100: STATIC_INLINE const char *fp_print(fptype *fx) ! 101: { ! 102: static char fs[32]; ! 103: bool n, d; ! 104: ! 105: n = signbit(*fx) ? 1 : 0; ! 106: d = isnormal(*fx) ? 0 : 1; ! 107: ! 108: if (isinf(*fx)) { ! 109: sprintf(fs, "%c%s", n?'-':'+', "inf"); ! 110: } else if (isnan(*fx)) { ! 111: sprintf(fs, "%c%s", n?'-':'+', "nan"); ! 112: } else { ! 113: if (n) ! 114: *fx *= -1.0; ! 115: #ifdef USE_LONG_DOUBLE ! 116: sprintf(fs, "%c%#.16Le%s%s", n?'-':'+', *fx, "", d?"D":""); ! 117: #else ! 118: sprintf(fs, "%c%#.16e%s%s", n?'-':'+', *fx, "", d?"D":""); ! 119: #endif ! 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 0; /* FIXME: how to detect SNAN */ ! 129: } ! 130: STATIC_INLINE void fp_unset_snan(fptype *fp) ! 131: { ! 132: /* FIXME: how to unset SNAN */ ! 133: } ! 134: STATIC_INLINE bool fp_is_nan (fptype *fp) ! 135: { ! 136: return isnan(*fp) != 0; ! 137: } ! 138: STATIC_INLINE bool fp_is_infinity (fptype *fp) ! 139: { ! 140: return isinf(*fp) != 0; ! 141: } ! 142: STATIC_INLINE bool fp_is_zero(fptype *fp) ! 143: { ! 144: return (*fp == 0.0); ! 145: } ! 146: STATIC_INLINE bool fp_is_neg(fptype *fp) ! 147: { ! 148: return signbit(*fp) != 0; ! 149: } ! 150: STATIC_INLINE bool fp_is_denormal(fptype *fp) ! 151: { ! 152: return false; ! 153: //return (isnormal(*fp) == 0); /* FIXME: how to differ denormal/unnormal? */ ! 154: } ! 155: STATIC_INLINE bool fp_is_unnormal(fptype *fp) ! 156: { ! 157: return false; ! 158: //return (isnormal(*fp) == 0); /* FIXME: how to differ denormal/unnormal? */ ! 159: } ! 160: ! 161: /* Function for normalizing unnormals FIXME: how to do this with native floats? */ ! 162: STATIC_INLINE void fp_normalize(fptype *fp) ! 163: { ! 164: } ! 165: ! 166: /* Functions for converting between float formats */ ! 167: /* FIXME: how to preserve/fix denormals and unnormals? */ ! 168: ! 169: STATIC_INLINE void to_single(fptype *fp, uae_u32 wrd1) ! 170: { ! 171: union { ! 172: float f; ! 173: uae_u32 u; ! 174: } val; ! 175: ! 176: val.u = wrd1; ! 177: *fp = (fptype) val.f; ! 178: } ! 179: STATIC_INLINE uae_u32 from_single(fptype *fp) ! 180: { ! 181: union { ! 182: float f; ! 183: uae_u32 u; ! 184: } val; ! 185: ! 186: val.f = (float) *fp; ! 187: return val.u; ! 188: } ! 189: ! 190: STATIC_INLINE void to_double(fptype *fp, uae_u32 wrd1, uae_u32 wrd2) ! 191: { ! 192: union { ! 193: double d; ! 194: uae_u32 u[2]; ! 195: } val; ! 196: ! 197: #ifdef WORDS_BIGENDIAN ! 198: val.u[0] = wrd1; ! 199: val.u[1] = wrd2; ! 200: #else ! 201: val.u[1] = wrd1; ! 202: val.u[0] = wrd2; ! 203: #endif ! 204: *fp = (fptype) val.d; ! 205: } ! 206: STATIC_INLINE void from_double(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2) ! 207: { ! 208: union { ! 209: double d; ! 210: uae_u32 u[2]; ! 211: } val; ! 212: ! 213: val.d = (double) *fp; ! 214: #ifdef WORDS_BIGENDIAN ! 215: *wrd1 = val.u[0]; ! 216: *wrd2 = val.u[1]; ! 217: #else ! 218: *wrd1 = val.u[1]; ! 219: *wrd2 = val.u[0]; ! 220: #endif ! 221: } ! 222: #ifdef USE_LONG_DOUBLE ! 223: STATIC_INLINE void to_exten(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) ! 224: { ! 225: union { ! 226: long double ld; ! 227: uae_u32 u[3]; ! 228: } val; ! 229: ! 230: #if WORDS_BIGENDIAN ! 231: val.u[0] = (wrd1 & 0xffff0000) | ((wrd2 & 0xffff0000) >> 16); ! 232: val.u[1] = (wrd2 & 0x0000ffff) | ((wrd3 & 0xffff0000) >> 16); ! 233: val.u[2] = (wrd3 & 0x0000ffff) << 16; ! 234: #else ! 235: val.u[0] = wrd3; ! 236: val.u[1] = wrd2; ! 237: val.u[2] = wrd1 >> 16; ! 238: #endif ! 239: *fp = val.ld; ! 240: } ! 241: STATIC_INLINE void from_exten(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3) ! 242: { ! 243: union { ! 244: long double ld; ! 245: uae_u32 u[3]; ! 246: } val; ! 247: ! 248: val.ld = *fp; ! 249: #if WORDS_BIGENDIAN ! 250: *wrd1 = val.u[0] & 0xffff0000; ! 251: *wrd2 = ((val.u[0] & 0x0000ffff) << 16) | ((val.u[1] & 0xffff0000) >> 16); ! 252: *wrd3 = ((val.u[1] & 0x0000ffff) << 16) | ((val.u[2] & 0xffff0000) >> 16); ! 253: #else ! 254: *wrd3 = val.u[0]; ! 255: *wrd2 = val.u[1]; ! 256: *wrd1 = val.u[2] << 16; ! 257: #endif ! 258: } ! 259: #else // if !USE_LONG_DOUBLE ! 260: static const double twoto32 = 4294967296.0; ! 261: STATIC_INLINE void to_exten(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) ! 262: { ! 263: double frac; ! 264: if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { ! 265: *fp = (wrd1 & 0x80000000) ? -0.0 : +0.0; ! 266: return; ! 267: } ! 268: frac = ((double)wrd2 + ((double)wrd3 / twoto32)) / 2147483648.0; ! 269: if (wrd1 & 0x80000000) ! 270: frac = -frac; ! 271: *fp = ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383); ! 272: } ! 273: STATIC_INLINE void from_exten(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3) ! 274: { ! 275: int expon; ! 276: double frac; ! 277: fptype v; ! 278: ! 279: v = *fp; ! 280: if (v == 0.0) { ! 281: *wrd1 = signbit(v) ? 0x80000000 : 0; ! 282: *wrd2 = 0; ! 283: *wrd3 = 0; ! 284: return; ! 285: } ! 286: if (v < 0) { ! 287: *wrd1 = 0x80000000; ! 288: v = -v; ! 289: } else { ! 290: *wrd1 = 0; ! 291: } ! 292: frac = frexp (v, &expon); ! 293: frac += 0.5 / (twoto32 * twoto32); ! 294: if (frac >= 1.0) { ! 295: frac /= 2.0; ! 296: expon++; ! 297: } ! 298: *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16); ! 299: *wrd2 = (uae_u32) (frac * twoto32); ! 300: *wrd3 = (uae_u32) ((frac * twoto32 - *wrd2) * twoto32); ! 301: } ! 302: #endif // !USE_LONG_DOUBLE ! 303: STATIC_INLINE void to_exten_fmovem(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) ! 304: { ! 305: to_exten(fp, wrd1, wrd2, wrd3); ! 306: } ! 307: STATIC_INLINE void from_exten_fmovem(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3) ! 308: { ! 309: from_exten(fp, wrd1, wrd2, wrd3); ! 310: } ! 311: ! 312: STATIC_INLINE void to_pack (fptype *fp, uae_u32 *wrd) ! 313: { ! 314: char *cp; ! 315: char str[100]; ! 316: ! 317: if (((wrd[0] >> 16) & 0x7fff) == 0x7fff) { ! 318: // infinity has extended exponent and all 0 packed fraction ! 319: // nans are copies bit by bit ! 320: to_exten(fp, wrd[0], wrd[1], wrd[2]); ! 321: return; ! 322: } ! 323: if (!(wrd[0] & 0xf) && !wrd[1] && !wrd[2]) { ! 324: // exponent is not cared about, if mantissa is zero ! 325: wrd[0] &= 0x80000000; ! 326: to_exten(fp, wrd[0], wrd[1], wrd[2]); ! 327: return; ! 328: } ! 329: ! 330: cp = str; ! 331: if (wrd[0] & 0x80000000) ! 332: *cp++ = '-'; ! 333: *cp++ = (wrd[0] & 0xf) + '0'; ! 334: *cp++ = '.'; ! 335: *cp++ = ((wrd[1] >> 28) & 0xf) + '0'; ! 336: *cp++ = ((wrd[1] >> 24) & 0xf) + '0'; ! 337: *cp++ = ((wrd[1] >> 20) & 0xf) + '0'; ! 338: *cp++ = ((wrd[1] >> 16) & 0xf) + '0'; ! 339: *cp++ = ((wrd[1] >> 12) & 0xf) + '0'; ! 340: *cp++ = ((wrd[1] >> 8) & 0xf) + '0'; ! 341: *cp++ = ((wrd[1] >> 4) & 0xf) + '0'; ! 342: *cp++ = ((wrd[1] >> 0) & 0xf) + '0'; ! 343: *cp++ = ((wrd[2] >> 28) & 0xf) + '0'; ! 344: *cp++ = ((wrd[2] >> 24) & 0xf) + '0'; ! 345: *cp++ = ((wrd[2] >> 20) & 0xf) + '0'; ! 346: *cp++ = ((wrd[2] >> 16) & 0xf) + '0'; ! 347: *cp++ = ((wrd[2] >> 12) & 0xf) + '0'; ! 348: *cp++ = ((wrd[2] >> 8) & 0xf) + '0'; ! 349: *cp++ = ((wrd[2] >> 4) & 0xf) + '0'; ! 350: *cp++ = ((wrd[2] >> 0) & 0xf) + '0'; ! 351: *cp++ = 'E'; ! 352: if (wrd[0] & 0x40000000) ! 353: *cp++ = '-'; ! 354: *cp++ = ((wrd[0] >> 24) & 0xf) + '0'; ! 355: *cp++ = ((wrd[0] >> 20) & 0xf) + '0'; ! 356: *cp++ = ((wrd[0] >> 16) & 0xf) + '0'; ! 357: *cp = 0; ! 358: ! 359: #ifdef USE_LONG_DOUBLE ! 360: sscanf (str, "%Le", fp); ! 361: #else ! 362: sscanf (str, "%le", fp); ! 363: #endif ! 364: } ! 365: STATIC_INLINE void from_pack (fptype *fp, uae_u32 *wrd, int kfactor) ! 366: { ! 367: int i, j, t; ! 368: int exp; ! 369: int ndigits; ! 370: char *cp, *strp; ! 371: char str[100]; ! 372: ! 373: if (fp_is_nan (fp)) { ! 374: // copy bit by bit, handle signaling nan ! 375: from_exten(fp, &wrd[0], &wrd[1], &wrd[2]); ! 376: return; ! 377: } ! 378: if (fp_is_infinity (fp)) { ! 379: // extended exponent and all 0 packed fraction ! 380: from_exten(fp, &wrd[0], &wrd[1], &wrd[2]); ! 381: wrd[1] = wrd[2] = 0; ! 382: return; ! 383: } ! 384: ! 385: wrd[0] = wrd[1] = wrd[2] = 0; ! 386: ! 387: #ifdef USE_LONG_DOUBLE ! 388: sprintf (str, "%#.17Le", *fp); ! 389: #else ! 390: sprintf (str, "%#.17e", *fp); ! 391: #endif ! 392: ! 393: // get exponent ! 394: cp = str; ! 395: while (*cp != 'e') { ! 396: if (*cp == 0) ! 397: return; ! 398: cp++; ! 399: } ! 400: cp++; ! 401: if (*cp == '+') ! 402: cp++; ! 403: exp = atoi (cp); ! 404: ! 405: // remove trailing zeros ! 406: cp = str; ! 407: while (*cp != 'e') ! 408: cp++; ! 409: cp[0] = 0; ! 410: cp--; ! 411: while (cp > str && *cp == '0') { ! 412: *cp = 0; ! 413: cp--; ! 414: } ! 415: ! 416: cp = str; ! 417: // get sign ! 418: if (*cp == '-') { ! 419: cp++; ! 420: wrd[0] = 0x80000000; ! 421: } else if (*cp == '+') { ! 422: cp++; ! 423: } ! 424: strp = cp; ! 425: ! 426: if (kfactor <= 0) { ! 427: ndigits = abs (exp) + (-kfactor) + 1; ! 428: } else { ! 429: if (kfactor > 17) { ! 430: kfactor = 17; ! 431: fpsr_set_exception(0x00002000); // OPERR ! 432: } ! 433: ndigits = kfactor; ! 434: } ! 435: ! 436: if (ndigits < 0) ! 437: ndigits = 0; ! 438: if (ndigits > 16) ! 439: ndigits = 16; ! 440: ! 441: // remove decimal point ! 442: strp[1] = strp[0]; ! 443: strp++; ! 444: // add trailing zeros ! 445: i = strlen (strp); ! 446: cp = strp + i; ! 447: while (i < ndigits) { ! 448: *cp++ = '0'; ! 449: i++; ! 450: } ! 451: i = ndigits + 1; ! 452: while (i < 17) { ! 453: strp[i] = 0; ! 454: i++; ! 455: } ! 456: *cp = 0; ! 457: i = ndigits - 1; ! 458: // need to round? ! 459: if (i >= 0 && strp[i + 1] >= '5') { ! 460: while (i >= 0) { ! 461: strp[i]++; ! 462: if (strp[i] <= '9') ! 463: break; ! 464: if (i == 0) { ! 465: strp[i] = '1'; ! 466: exp++; ! 467: } else { ! 468: strp[i] = '0'; ! 469: } ! 470: i--; ! 471: } ! 472: } ! 473: strp[ndigits] = 0; ! 474: ! 475: // store first digit of mantissa ! 476: cp = strp; ! 477: wrd[0] |= *cp++ - '0'; ! 478: ! 479: // store rest of mantissa ! 480: for (j = 1; j < 3; j++) { ! 481: for (i = 0; i < 8; i++) { ! 482: wrd[j] <<= 4; ! 483: if (*cp >= '0' && *cp <= '9') ! 484: wrd[j] |= *cp++ - '0'; ! 485: } ! 486: } ! 487: ! 488: // exponent ! 489: if (exp < 0) { ! 490: wrd[0] |= 0x40000000; ! 491: exp = -exp; ! 492: } ! 493: if (exp > 9999) // ?? ! 494: exp = 9999; ! 495: if (exp > 999) { ! 496: int d = exp / 1000; ! 497: wrd[0] |= d << 12; ! 498: exp -= d * 1000; ! 499: fpsr_set_exception(0x00002000); // OPERR ! 500: } ! 501: i = 100; ! 502: t = 0; ! 503: while (i >= 1) { ! 504: int d = exp / i; ! 505: t <<= 4; ! 506: t |= d; ! 507: exp -= d * i; ! 508: i /= 10; ! 509: } ! 510: wrd[0] |= t << 16; ! 511: } ! 512: ! 513: #ifndef USE_HOST_ROUNDING ! 514: #ifdef USE_LONG_DOUBLE ! 515: #define fp_round_to_minus_infinity(x) floorl(x) ! 516: #define fp_round_to_plus_infinity(x) ceill(x) ! 517: #define fp_round_to_zero(x) ((x) >= 0.0 ? floorl(x) : ceill(x)) ! 518: #define fp_round_to_nearest(x) roundl(x) ! 519: #else // if !USE_LONG_DOUBLE ! 520: #define fp_round_to_minus_infinity(x) floor(x) ! 521: #define fp_round_to_plus_infinity(x) ceil(x) ! 522: #define fp_round_to_zero(x) ((x) >= 0.0 ? floor(x) : ceil(x)) ! 523: #define fp_round_to_nearest(x) round(x) ! 524: #endif // !USE_LONG_DOUBLE ! 525: #endif // USE_HOST_ROUNDING ! 526: ! 527: STATIC_INLINE uae_s64 to_int(fptype *src, int size) ! 528: { ! 529: static fptype fxsizes[6] = ! 530: { ! 531: -128.0, 127.0, ! 532: -32768.0, 32767.0, ! 533: -2147483648.0, 2147483647.0 ! 534: }; ! 535: ! 536: if (*src < fxsizes[size * 2 + 0]) ! 537: *src = fxsizes[size * 2 + 0]; ! 538: if (*src > fxsizes[size * 2 + 1]) ! 539: *src = fxsizes[size * 2 + 1]; ! 540: #ifdef USE_HOST_ROUNDING ! 541: #ifdef USE_LONG_DOUBLE ! 542: return lrintl(*src); ! 543: #else ! 544: return lrint(*src); ! 545: #endif ! 546: #else ! 547: switch (regs.fpcr & FPCR_ROUNDING_MODE) ! 548: { ! 549: case FPCR_ROUND_ZERO: ! 550: return fp_round_to_zero (*src); ! 551: case FPCR_ROUND_MINF: ! 552: return fp_round_to_minus_infinity (*src); ! 553: case FPCR_ROUND_NEAR: ! 554: return fp_round_to_nearest (*src); ! 555: case FPCR_ROUND_PINF: ! 556: return fp_round_to_plus_infinity (*src); ! 557: default: ! 558: return (int) *src; ! 559: } ! 560: #endif ! 561: } ! 562: STATIC_INLINE fptype from_int(uae_s32 src) ! 563: { ! 564: return (fptype) src; ! 565: } ! 566: ! 567: /* Functions for returning exception state data */ ! 568: /* (almost impossible to emulate using native floats) */ ! 569: STATIC_INLINE fptype fp_get_internal_overflow(void) ! 570: { ! 571: return 0.0; ! 572: } ! 573: STATIC_INLINE fptype fp_get_internal_underflow(void) ! 574: { ! 575: return 0.0; ! 576: } ! 577: STATIC_INLINE fptype fp_get_internal(void) ! 578: { ! 579: return 0.0; ! 580: } ! 581: STATIC_INLINE fptype fp_get_internal_round(void) ! 582: { ! 583: return 0.0; ! 584: } ! 585: STATIC_INLINE fptype fp_get_internal_round_all(void) ! 586: { ! 587: return 0.0; ! 588: } ! 589: STATIC_INLINE fptype fp_get_internal_round_exten(void) ! 590: { ! 591: return 0.0; ! 592: } ! 593: STATIC_INLINE uae_u32 fp_get_internal_grs(void) ! 594: { ! 595: return 0.0; ! 596: } ! 597: ! 598: /* Function for denormalizing */ ! 599: STATIC_INLINE void fp_denormalize(fptype *fp, int esign) ! 600: { ! 601: // do nothing ! 602: } ! 603: ! 604: /* Functions for rounding */ ! 605: ! 606: // round to float with extended precision exponent ! 607: STATIC_INLINE void fp_round32(fptype *fp) ! 608: { ! 609: int expon; ! 610: float mant; ! 611: #ifdef USE_LONG_DOUBLE ! 612: mant = (float)(frexpl(*fp, &expon) * 2.0); ! 613: *fp = ldexpl((fptype)mant, expon - 1); ! 614: #else ! 615: mant = (float)(frexp(*fp, &expon) * 2.0); ! 616: *fp = ldexp((fptype)mant, expon - 1); ! 617: #endif ! 618: } ! 619: ! 620: // round to double with extended precision exponent ! 621: STATIC_INLINE void fp_round64(fptype *fp) ! 622: { ! 623: int expon; ! 624: double mant; ! 625: #ifdef USE_LONG_DOUBLE ! 626: mant = (double)(frexpl(*fp, &expon) * 2.0); ! 627: *fp = ldexpl((fptype)mant, expon - 1); ! 628: #else ! 629: mant = (double)(frexp(*fp, &expon) * 2.0); ! 630: *fp = ldexp((fptype)mant, expon - 1); ! 631: #endif ! 632: } ! 633: ! 634: // round to float ! 635: STATIC_INLINE void fp_round_single(fptype *fp) ! 636: { ! 637: *fp = (float) *fp; ! 638: } ! 639: ! 640: // round to double ! 641: STATIC_INLINE void fp_round_double(fptype *fp) ! 642: { ! 643: *fp = (double) *fp; ! 644: } ! 645: ! 646: // round to selected precision ! 647: STATIC_INLINE void fp_round(fptype *fp) ! 648: { ! 649: switch(fp_rnd_prec) { ! 650: case 32: ! 651: *fp = (float) *fp; ! 652: break; ! 653: case 64: ! 654: *fp = (double) *fp; ! 655: break; ! 656: default: ! 657: break; ! 658: } ! 659: } ! 660: ! 661: ! 662: /* Arithmetic functions */ ! 663: ! 664: #ifdef USE_LONG_DOUBLE ! 665: ! 666: STATIC_INLINE void fp_move(fptype *a, fptype *b) ! 667: { ! 668: *a = *b; ! 669: fp_round(a); ! 670: } ! 671: STATIC_INLINE void fp_move_single(fptype *a, fptype *b) ! 672: { ! 673: *a = *b; ! 674: fp_round_single(a); ! 675: } ! 676: STATIC_INLINE void fp_move_double(fptype *a, fptype *b) ! 677: { ! 678: *a = *b; ! 679: fp_round_double(a); ! 680: } ! 681: STATIC_INLINE void fp_int(fptype *a, fptype *b) ! 682: { ! 683: #ifdef USE_HOST_ROUNDING ! 684: *a = rintl(*b); ! 685: #else ! 686: switch (regs.fpcr & FPCR_ROUNDING_MODE) ! 687: { ! 688: case FPCR_ROUND_NEAR: ! 689: *a = fp_round_to_nearest(*b); ! 690: break; ! 691: case FPCR_ROUND_ZERO: ! 692: *a = fp_round_to_zero(*b); ! 693: break; ! 694: case FPCR_ROUND_MINF: ! 695: *a = fp_round_to_minus_infinity(*b); ! 696: break; ! 697: case FPCR_ROUND_PINF: ! 698: *a = fp_round_to_plus_infinity(*b); ! 699: break; ! 700: default: /* never reached */ ! 701: break; ! 702: } ! 703: #endif ! 704: fp_round(a); ! 705: } ! 706: STATIC_INLINE void fp_sinh(fptype *a, fptype *b) ! 707: { ! 708: *a = sinhl(*b); ! 709: fp_round(a); ! 710: } ! 711: STATIC_INLINE void fp_intrz(fptype *a, fptype *b) ! 712: { ! 713: #ifdef USE_HOST_ROUNDING ! 714: *a = truncl(*b); ! 715: #else ! 716: *a = fp_round_to_zero (*b); ! 717: #endif ! 718: fp_round(a); ! 719: } ! 720: STATIC_INLINE void fp_sqrt(fptype *a, fptype *b) ! 721: { ! 722: *a = sqrtl(*b); ! 723: fp_round(a); ! 724: } ! 725: STATIC_INLINE void fp_sqrt_single(fptype *a, fptype *b) ! 726: { ! 727: *a = sqrtl(*b); ! 728: fp_round_single(a); ! 729: } ! 730: STATIC_INLINE void fp_sqrt_double(fptype *a, fptype *b) ! 731: { ! 732: *a = sqrtl(*b); ! 733: fp_round_double(a); ! 734: } ! 735: STATIC_INLINE void fp_lognp1(fptype *a, fptype *b) ! 736: { ! 737: *a = log1pl(*b); ! 738: fp_round(a); ! 739: } ! 740: STATIC_INLINE void fp_etoxm1(fptype *a, fptype *b) ! 741: { ! 742: *a = expm1l(*b); ! 743: fp_round(a); ! 744: } ! 745: STATIC_INLINE void fp_tanh(fptype *a, fptype *b) ! 746: { ! 747: *a = tanhl(*b); ! 748: fp_round(a); ! 749: } ! 750: STATIC_INLINE void fp_atan(fptype *a, fptype *b) ! 751: { ! 752: *a = atanl(*b); ! 753: fp_round(a); ! 754: } ! 755: STATIC_INLINE void fp_asin(fptype *a, fptype *b) ! 756: { ! 757: *a = asinl(*b); ! 758: fp_round(a); ! 759: } ! 760: STATIC_INLINE void fp_atanh(fptype *a, fptype *b) ! 761: { ! 762: *a = atanhl(*b); ! 763: fp_round(a); ! 764: } ! 765: STATIC_INLINE void fp_sin(fptype *a, fptype *b) ! 766: { ! 767: *a = sinl(*b); ! 768: fp_round(a); ! 769: } ! 770: STATIC_INLINE void fp_tan(fptype *a, fptype *b) ! 771: { ! 772: *a = tanl(*b); ! 773: fp_round(a); ! 774: } ! 775: STATIC_INLINE void fp_etox(fptype *a, fptype *b) ! 776: { ! 777: *a = expl(*b); ! 778: fp_round(a); ! 779: } ! 780: STATIC_INLINE void fp_twotox(fptype *a, fptype *b) ! 781: { ! 782: *a = powl(2.0, *b); ! 783: fp_round(a); ! 784: } ! 785: STATIC_INLINE void fp_tentox(fptype *a, fptype *b) ! 786: { ! 787: *a = powl(10.0, *b); ! 788: fp_round(a); ! 789: } ! 790: STATIC_INLINE void fp_logn(fptype *a, fptype *b) ! 791: { ! 792: *a = logl(*b); ! 793: fp_round(a); ! 794: } ! 795: STATIC_INLINE void fp_log10(fptype *a, fptype *b) ! 796: { ! 797: *a = log10l(*b); ! 798: fp_round(a); ! 799: } ! 800: STATIC_INLINE void fp_log2(fptype *a, fptype *b) ! 801: { ! 802: *a = log2l(*b); ! 803: fp_round(a); ! 804: } ! 805: STATIC_INLINE void fp_abs(fptype *a, fptype *b) ! 806: { ! 807: *a = fabsl(*b); ! 808: fp_round(a); ! 809: } ! 810: STATIC_INLINE void fp_abs_single(fptype *a, fptype *b) ! 811: { ! 812: *a = fabsl(*b); ! 813: fp_round_single(a); ! 814: } ! 815: STATIC_INLINE void fp_abs_double(fptype *a, fptype *b) ! 816: { ! 817: *a = fabsl(*b); ! 818: fp_round_double(a); ! 819: } ! 820: STATIC_INLINE void fp_cosh(fptype *a, fptype *b) ! 821: { ! 822: *a = coshl(*b); ! 823: fp_round(a); ! 824: } ! 825: STATIC_INLINE void fp_neg(fptype *a, fptype *b) ! 826: { ! 827: *a = -(*b); ! 828: fp_round(a); ! 829: } ! 830: STATIC_INLINE void fp_neg_single(fptype *a, fptype *b) ! 831: { ! 832: *a = -(*b); ! 833: fp_round_single(a); ! 834: } ! 835: STATIC_INLINE void fp_neg_double(fptype *a, fptype *b) ! 836: { ! 837: *a = -(*b); ! 838: fp_round_double(a); ! 839: } ! 840: STATIC_INLINE void fp_acos(fptype *a, fptype *b) ! 841: { ! 842: *a = acosl(*b); ! 843: fp_round(a); ! 844: } ! 845: STATIC_INLINE void fp_cos(fptype *a, fptype *b) ! 846: { ! 847: *a = cosl(*b); ! 848: fp_round(a); ! 849: } ! 850: STATIC_INLINE void fp_getexp(fptype *a, fptype *b) ! 851: { ! 852: int expon; ! 853: frexpl(*b, &expon); ! 854: *a = (long double) (expon - 1); ! 855: fp_round(a); ! 856: } ! 857: STATIC_INLINE void fp_getman(fptype *a, fptype *b) ! 858: { ! 859: int expon; ! 860: *a = frexpl(*b, &expon) * 2.0; ! 861: fp_round(a); ! 862: } ! 863: STATIC_INLINE void fp_div(fptype *a, fptype *b) ! 864: { ! 865: *a /= *b; ! 866: fp_round(a); ! 867: } ! 868: STATIC_INLINE void fp_div_single(fptype *a, fptype *b) ! 869: { ! 870: *a /= *b; ! 871: fp_round_single(a); ! 872: } ! 873: STATIC_INLINE void fp_div_double(fptype *a, fptype *b) ! 874: { ! 875: *a /= *b; ! 876: fp_round_double(a); ! 877: } ! 878: STATIC_INLINE void fp_mod(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s) ! 879: { ! 880: fptype quot; ! 881: #ifdef USE_HOST_ROUNDING ! 882: quot = truncl(*a / *b); ! 883: #else ! 884: quot = fp_round_to_zero(*a / *b); ! 885: #endif ! 886: if (quot < 0.0) { ! 887: *s = 1; ! 888: quot = -quot; ! 889: } else { ! 890: *s = 0; ! 891: } ! 892: *q = (uae_u64)quot; ! 893: *a = fmodl(*a, *b); ! 894: fp_round(a); ! 895: } ! 896: STATIC_INLINE void fp_add(fptype *a, fptype *b) ! 897: { ! 898: *a += *b; ! 899: fp_round(a); ! 900: } ! 901: STATIC_INLINE void fp_add_single(fptype *a, fptype *b) ! 902: { ! 903: *a += *b; ! 904: fp_round_single(a); ! 905: } ! 906: STATIC_INLINE void fp_add_double(fptype *a, fptype *b) ! 907: { ! 908: *a += *b; ! 909: fp_round_double(a); ! 910: } ! 911: STATIC_INLINE void fp_mul(fptype *a, fptype *b) ! 912: { ! 913: *a *= *b; ! 914: fp_round(a); ! 915: } ! 916: STATIC_INLINE void fp_mul_single(fptype *a, fptype *b) ! 917: { ! 918: *a *= *b; ! 919: fp_round_single(a); ! 920: } ! 921: STATIC_INLINE void fp_mul_double(fptype *a, fptype *b) ! 922: { ! 923: *a *= *b; ! 924: fp_round_double(a); ! 925: } ! 926: STATIC_INLINE void fp_sgldiv(fptype *a, fptype *b) ! 927: { ! 928: fptype z; ! 929: float mant; ! 930: int expon; ! 931: z = *a / *b; ! 932: ! 933: mant = (float)(frexpl(z, &expon) * 2.0); ! 934: *a = ldexpl((fptype)mant, expon - 1); ! 935: } ! 936: STATIC_INLINE void fp_rem(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s) ! 937: { ! 938: fptype quot; ! 939: #ifdef USE_HOST_ROUNDING ! 940: quot = roundl(*a / *b); ! 941: #else ! 942: quot = fp_round_to_nearest(*a / *b); ! 943: #endif ! 944: if (quot < 0.0) { ! 945: *s = 1; ! 946: quot = -quot; ! 947: } else { ! 948: *s = 0; ! 949: } ! 950: *q = (uae_u64)quot; ! 951: *a = remainderl(*a, *b); ! 952: fp_round(a); ! 953: } ! 954: STATIC_INLINE void fp_scale(fptype *a, fptype *b) ! 955: { ! 956: *a = ldexpl(*a, (int) *b); ! 957: fp_round(a); ! 958: } ! 959: STATIC_INLINE void fp_sglmul(fptype *a, fptype *b) ! 960: { ! 961: fptype z; ! 962: float mant; ! 963: int expon; ! 964: /* FIXME: truncate mantissa of a and b to single precision */ ! 965: z = *a * (*b); ! 966: ! 967: mant = (float)(frexpl(z, &expon) * 2.0); ! 968: *a = ldexpl((fptype)mant, expon - 1); ! 969: } ! 970: STATIC_INLINE void fp_sub(fptype *a, fptype *b) ! 971: { ! 972: *a -= *b; ! 973: fp_round(a); ! 974: } ! 975: STATIC_INLINE void fp_sub_single(fptype *a, fptype *b) ! 976: { ! 977: *a -= *b; ! 978: fp_round_single(a); ! 979: } ! 980: STATIC_INLINE void fp_sub_double(fptype *a, fptype *b) ! 981: { ! 982: *a -= *b; ! 983: fp_round_double(a); ! 984: } ! 985: STATIC_INLINE void fp_cmp(fptype *a, fptype *b) ! 986: { ! 987: *a = (*a - *b); /* FIXME: comparing is different from subtraction */ ! 988: } ! 989: STATIC_INLINE void fp_tst(fptype *a, fptype *b) ! 990: { ! 991: *a = *b; /* FIXME: test b */ ! 992: } ! 993: ! 994: #else // if !USE_LONG_DOUBLE ! 995: ! 996: STATIC_INLINE void fp_move(fptype *a, fptype *b) ! 997: { ! 998: *a = *b; ! 999: fp_round(a); ! 1000: } ! 1001: STATIC_INLINE void fp_move_single(fptype *a, fptype *b) ! 1002: { ! 1003: *a = *b; ! 1004: fp_round_single(a); ! 1005: } ! 1006: STATIC_INLINE void fp_move_double(fptype *a, fptype *b) ! 1007: { ! 1008: *a = *b; ! 1009: fp_round_double(a); ! 1010: } ! 1011: STATIC_INLINE void fp_int(fptype *a, fptype *b) ! 1012: { ! 1013: #ifdef USE_HOST_ROUNDING ! 1014: *a = rint(*b); ! 1015: #else ! 1016: switch (regs.fpcr & FPCR_ROUNDING_MODE) ! 1017: { ! 1018: case FPCR_ROUND_NEAR: ! 1019: *a = fp_round_to_nearest(*b); ! 1020: break; ! 1021: case FPCR_ROUND_ZERO: ! 1022: *a = fp_round_to_zero(*b); ! 1023: break; ! 1024: case FPCR_ROUND_MINF: ! 1025: *a = fp_round_to_minus_infinity(*b); ! 1026: break; ! 1027: case FPCR_ROUND_PINF: ! 1028: *a = fp_round_to_plus_infinity(*b); ! 1029: break; ! 1030: default: /* never reached */ ! 1031: break; ! 1032: } ! 1033: #endif ! 1034: fp_round(a); ! 1035: } ! 1036: STATIC_INLINE void fp_sinh(fptype *a, fptype *b) ! 1037: { ! 1038: *a = sinh(*b); ! 1039: fp_round(a); ! 1040: } ! 1041: STATIC_INLINE void fp_intrz(fptype *a, fptype *b) ! 1042: { ! 1043: #ifdef USE_HOST_ROUNDING ! 1044: *a = trunc(*b); ! 1045: #else ! 1046: *a = fp_round_to_zero (*b); ! 1047: #endif ! 1048: fp_round(a); ! 1049: } ! 1050: STATIC_INLINE void fp_sqrt(fptype *a, fptype *b) ! 1051: { ! 1052: *a = sqrt(*b); ! 1053: fp_round(a); ! 1054: } ! 1055: STATIC_INLINE void fp_sqrt_single(fptype *a, fptype *b) ! 1056: { ! 1057: *a = sqrt(*b); ! 1058: fp_round_single(a); ! 1059: } ! 1060: STATIC_INLINE void fp_sqrt_double(fptype *a, fptype *b) ! 1061: { ! 1062: *a = sqrt(*b); ! 1063: fp_round_double(a); ! 1064: } ! 1065: STATIC_INLINE void fp_lognp1(fptype *a, fptype *b) ! 1066: { ! 1067: *a = log1p(*b); ! 1068: fp_round(a); ! 1069: } ! 1070: STATIC_INLINE void fp_etoxm1(fptype *a, fptype *b) ! 1071: { ! 1072: *a = expm1(*b); ! 1073: fp_round(a); ! 1074: } ! 1075: STATIC_INLINE void fp_tanh(fptype *a, fptype *b) ! 1076: { ! 1077: *a = tanh(*b); ! 1078: fp_round(a); ! 1079: } ! 1080: STATIC_INLINE void fp_atan(fptype *a, fptype *b) ! 1081: { ! 1082: *a = atan(*b); ! 1083: fp_round(a); ! 1084: } ! 1085: STATIC_INLINE void fp_asin(fptype *a, fptype *b) ! 1086: { ! 1087: *a = asin(*b); ! 1088: fp_round(a); ! 1089: } ! 1090: STATIC_INLINE void fp_atanh(fptype *a, fptype *b) ! 1091: { ! 1092: *a = atanh(*b); ! 1093: fp_round(a); ! 1094: } ! 1095: STATIC_INLINE void fp_sin(fptype *a, fptype *b) ! 1096: { ! 1097: *a = sin(*b); ! 1098: fp_round(a); ! 1099: } ! 1100: STATIC_INLINE void fp_tan(fptype *a, fptype *b) ! 1101: { ! 1102: *a = tan(*b); ! 1103: fp_round(a); ! 1104: } ! 1105: STATIC_INLINE void fp_etox(fptype *a, fptype *b) ! 1106: { ! 1107: *a = exp(*b); ! 1108: fp_round(a); ! 1109: } ! 1110: STATIC_INLINE void fp_twotox(fptype *a, fptype *b) ! 1111: { ! 1112: *a = pow(2.0, *b); ! 1113: fp_round(a); ! 1114: } ! 1115: STATIC_INLINE void fp_tentox(fptype *a, fptype *b) ! 1116: { ! 1117: *a = pow(10.0, *b); ! 1118: fp_round(a); ! 1119: } ! 1120: STATIC_INLINE void fp_logn(fptype *a, fptype *b) ! 1121: { ! 1122: *a = log(*b); ! 1123: fp_round(a); ! 1124: } ! 1125: STATIC_INLINE void fp_log10(fptype *a, fptype *b) ! 1126: { ! 1127: *a = log10(*b); ! 1128: fp_round(a); ! 1129: } ! 1130: STATIC_INLINE void fp_log2(fptype *a, fptype *b) ! 1131: { ! 1132: *a = log2(*b); ! 1133: fp_round(a); ! 1134: } ! 1135: STATIC_INLINE void fp_abs(fptype *a, fptype *b) ! 1136: { ! 1137: *a = fabs(*b); ! 1138: fp_round(a); ! 1139: } ! 1140: STATIC_INLINE void fp_abs_single(fptype *a, fptype *b) ! 1141: { ! 1142: *a = fabs(*b); ! 1143: fp_round_single(a); ! 1144: } ! 1145: STATIC_INLINE void fp_abs_double(fptype *a, fptype *b) ! 1146: { ! 1147: *a = fabs(*b); ! 1148: fp_round_double(a); ! 1149: } ! 1150: STATIC_INLINE void fp_cosh(fptype *a, fptype *b) ! 1151: { ! 1152: *a = cosh(*b); ! 1153: fp_round(a); ! 1154: } ! 1155: STATIC_INLINE void fp_neg(fptype *a, fptype *b) ! 1156: { ! 1157: *a = -(*b); ! 1158: fp_round(a); ! 1159: } ! 1160: STATIC_INLINE void fp_neg_single(fptype *a, fptype *b) ! 1161: { ! 1162: *a = -(*b); ! 1163: fp_round_single(a); ! 1164: } ! 1165: STATIC_INLINE void fp_neg_double(fptype *a, fptype *b) ! 1166: { ! 1167: *a = -(*b); ! 1168: fp_round_double(a); ! 1169: } ! 1170: STATIC_INLINE void fp_acos(fptype *a, fptype *b) ! 1171: { ! 1172: *a = acos(*b); ! 1173: fp_round(a); ! 1174: } ! 1175: STATIC_INLINE void fp_cos(fptype *a, fptype *b) ! 1176: { ! 1177: *a = cos(*b); ! 1178: fp_round(a); ! 1179: } ! 1180: STATIC_INLINE void fp_getexp(fptype *a, fptype *b) ! 1181: { ! 1182: int expon; ! 1183: frexp(*b, &expon); ! 1184: *a = (long double) (expon - 1); ! 1185: fp_round(a); ! 1186: } ! 1187: STATIC_INLINE void fp_getman(fptype *a, fptype *b) ! 1188: { ! 1189: int expon; ! 1190: *a = frexp(*b, &expon) * 2.0; ! 1191: fp_round(a); ! 1192: } ! 1193: STATIC_INLINE void fp_div(fptype *a, fptype *b) ! 1194: { ! 1195: *a /= *b; ! 1196: fp_round(a); ! 1197: } ! 1198: STATIC_INLINE void fp_div_single(fptype *a, fptype *b) ! 1199: { ! 1200: *a /= *b; ! 1201: fp_round_single(a); ! 1202: } ! 1203: STATIC_INLINE void fp_div_double(fptype *a, fptype *b) ! 1204: { ! 1205: *a /= *b; ! 1206: fp_round_double(a); ! 1207: } ! 1208: STATIC_INLINE void fp_mod(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s) ! 1209: { ! 1210: fptype quot; ! 1211: #ifdef USE_HOST_ROUNDING ! 1212: quot = trunc(*a / *b); ! 1213: #else ! 1214: quot = fp_round_to_zero(*a / *b); ! 1215: #endif ! 1216: if (quot < 0.0) { ! 1217: *s = 1; ! 1218: quot = -quot; ! 1219: } else { ! 1220: *s = 0; ! 1221: } ! 1222: *q = (uae_u64)quot; ! 1223: *a = fmod(*a, *b); ! 1224: fp_round(a); ! 1225: } ! 1226: STATIC_INLINE void fp_add(fptype *a, fptype *b) ! 1227: { ! 1228: *a += *b; ! 1229: fp_round(a); ! 1230: } ! 1231: STATIC_INLINE void fp_add_single(fptype *a, fptype *b) ! 1232: { ! 1233: *a += *b; ! 1234: fp_round_single(a); ! 1235: } ! 1236: STATIC_INLINE void fp_add_double(fptype *a, fptype *b) ! 1237: { ! 1238: *a += *b; ! 1239: fp_round_double(a); ! 1240: } ! 1241: STATIC_INLINE void fp_mul(fptype *a, fptype *b) ! 1242: { ! 1243: *a *= *b; ! 1244: fp_round(a); ! 1245: } ! 1246: STATIC_INLINE void fp_mul_single(fptype *a, fptype *b) ! 1247: { ! 1248: *a *= *b; ! 1249: fp_round_single(a); ! 1250: } ! 1251: STATIC_INLINE void fp_mul_double(fptype *a, fptype *b) ! 1252: { ! 1253: *a *= *b; ! 1254: fp_round_double(a); ! 1255: } ! 1256: STATIC_INLINE void fp_sgldiv(fptype *a, fptype *b) ! 1257: { ! 1258: fptype z; ! 1259: float mant; ! 1260: int expon; ! 1261: z = *a / *b; ! 1262: ! 1263: mant = (float)(frexp(z, &expon) * 2.0); ! 1264: *a = ldexp((fptype)mant, expon - 1); ! 1265: } ! 1266: STATIC_INLINE void fp_rem(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s) ! 1267: { ! 1268: fptype quot; ! 1269: #ifdef USE_HOST_ROUNDING ! 1270: quot = round(*a / *b); ! 1271: #else ! 1272: quot = fp_round_to_nearest(*a / *b); ! 1273: #endif ! 1274: if (quot < 0.0) { ! 1275: *s = 1; ! 1276: quot = -quot; ! 1277: } else { ! 1278: *s = 0; ! 1279: } ! 1280: *q = (uae_u64)quot; ! 1281: *a = remainder(*a, *b); ! 1282: fp_round(a); ! 1283: } ! 1284: STATIC_INLINE void fp_scale(fptype *a, fptype *b) ! 1285: { ! 1286: *a = ldexp(*a, (int) *b); ! 1287: fp_round(a); ! 1288: } ! 1289: STATIC_INLINE void fp_sglmul(fptype *a, fptype *b) ! 1290: { ! 1291: fptype z; ! 1292: float mant; ! 1293: int expon; ! 1294: /* FIXME: truncate mantissa of a and b to single precision */ ! 1295: z = *a * (*b); ! 1296: ! 1297: mant = (float)(frexp(z, &expon) * 2.0); ! 1298: *a = ldexp((fptype)mant, expon - 1); ! 1299: } ! 1300: STATIC_INLINE void fp_sub(fptype *a, fptype *b) ! 1301: { ! 1302: *a -= *b; ! 1303: fp_round(a); ! 1304: } ! 1305: STATIC_INLINE void fp_sub_single(fptype *a, fptype *b) ! 1306: { ! 1307: *a -= *b; ! 1308: fp_round_single(a); ! 1309: } ! 1310: STATIC_INLINE void fp_sub_double(fptype *a, fptype *b) ! 1311: { ! 1312: *a -= *b; ! 1313: fp_round_double(a); ! 1314: } ! 1315: STATIC_INLINE void fp_cmp(fptype *a, fptype *b) ! 1316: { ! 1317: *a = (*a - *b); /* FIXME: comparing is different from subtraction */ ! 1318: } ! 1319: STATIC_INLINE void fp_tst(fptype *a, fptype *b) ! 1320: { ! 1321: *a = *b; /* FIXME: test b */ ! 1322: } ! 1323: ! 1324: #endif // !USE_LONG_DOUBLE ! 1325: ! 1326: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.