Annotation of previous/src/softfloat/fyl2x.c, revision 1.1.1.1

1.1       root        1: /*============================================================================
                      2: This source file is an extension to the SoftFloat IEC/IEEE Floating-point
                      3: Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator)
                      4: floating point emulation.
                      5: float_raise(float_flag_invalid)
                      6: THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
                      7: been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
                      8: RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
                      9: AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
                     10: COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
                     11: EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
                     12: INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
                     13: OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
                     14: 
                     15: Derivative works are acceptable, even for commercial purposes, so long as
                     16: (1) the source code for the derivative work includes prominent notice that
                     17: the work is derivative, and (2) the source code includes prominent notice with
                     18: these four paragraphs for those parts of this code that are retained.
                     19: =============================================================================*/
                     20: 
                     21: /*============================================================================
                     22:  * Written for Bochs (x86 achitecture simulator) by
                     23:  *            Stanislav Shwartsman [sshwarts at sourceforge net]
                     24:  * Adapted for lib/softfloat in MESS by Hans Ostermeyer (03/2012)
                     25:  * ==========================================================================*/
                     26: 
                     27: #define FLOAT128
                     28: 
                     29: #define USE_estimateDiv128To64
                     30: #include "mamesf.h"
                     31: #include "softfloat.h"
                     32: #include "fpu_constant.h"
                     33: 
                     34: static const floatx80 floatx80_log10_2 = { 0x3ffd, 0x9a209a84fbcff798U };
                     35: static const floatx80 floatx80_ln_2 = { 0x3ffe, 0xb17217f7d1cf79acU };
                     36: static const floatx80 floatx80_one = { 0x3fff, 0x8000000000000000U };
                     37: static const floatx80 floatx80_default_nan = { floatx80_default_nan_high, floatx80_default_nan_low };
                     38: 
                     39: #define packFloat_128(zHi, zLo) {(zHi), (zLo)}
                     40: #define PACK_FLOAT_128(hi,lo) packFloat_128(LIT64(hi),LIT64(lo))
                     41: 
                     42: #define EXP_BIAS 0x3FFF
                     43: 
                     44: 
                     45: static const float128 float128_one =
                     46:        packFloat_128(0x3fff000000000000U, 0x0000000000000000U);
                     47: static const float128 float128_two =
                     48:        packFloat_128(0x4000000000000000U, 0x0000000000000000U);
                     49: 
                     50: static const float128 float128_ln2inv2 =
                     51:        packFloat_128(0x400071547652b82fU, 0xe1777d0ffda0d23aU);
                     52: 
                     53: #define SQRT2_HALF_SIG  0xb504f333f9de6484U
                     54: 
                     55: extern float128 OddPoly(float128 x, float128 *arr, unsigned n);
                     56: 
                     57: #define L2_ARR_SIZE 9
                     58: 
                     59: static float128 ln_arr[L2_ARR_SIZE] =
                     60: {
                     61:        PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /*  1 */
                     62:        PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /*  3 */
                     63:        PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /*  5 */
                     64:        PACK_FLOAT_128(0x3ffc249249249249, 0x2492492492492492), /*  7 */
                     65:        PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /*  9 */
                     66:        PACK_FLOAT_128(0x3ffb745d1745d174, 0x5d1745d1745d1746), /* 11 */
                     67:        PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */
                     68:        PACK_FLOAT_128(0x3ffb111111111111, 0x1111111111111111), /* 15 */
                     69:        PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2)  /* 17 */
                     70: };
                     71: 
                     72: static float128 poly_ln(float128 x1)
                     73: {
                     74: /*
                     75:     //
                     76:     //                     3     5     7     9     11     13     15
                     77:     //        1+u         u     u     u     u     u      u      u
                     78:     // 1/2 ln ---  ~ u + --- + --- + --- + --- + ---- + ---- + ---- =
                     79:     //        1-u         3     5     7     9     11     13     15
                     80:     //
                     81:     //                     2     4     6     8     10     12     14
                     82:     //                    u     u     u     u     u      u      u
                     83:     //       = u * [ 1 + --- + --- + --- + --- + ---- + ---- + ---- ] =
                     84:     //                    3     5     7     9     11     13     15
                     85:     //
                     86:     //           3                          3
                     87:     //          --       4k                --        4k+2
                     88:     //   p(u) = >  C  * u           q(u) = >  C   * u
                     89:     //          --  2k                     --  2k+1
                     90:     //          k=0                        k=0
                     91:     //
                     92:     //          1+u                 2
                     93:     //   1/2 ln --- ~ u * [ p(u) + u * q(u) ]
                     94:     //          1-u
                     95:     //
                     96: */
                     97:        return OddPoly(x1, ln_arr, L2_ARR_SIZE);
                     98: }
                     99: 
                    100: /* required sqrt(2)/2 < x < sqrt(2) */
                    101: static float128 poly_l2(float128 x)
                    102: {
                    103:        /* using float128 for approximation */
                    104:        float128 x_p1 = float128_add(x, float128_one);
                    105:        float128 x_m1 = float128_sub(x, float128_one);
                    106:        x = float128_div(x_m1, x_p1);
                    107:        x = poly_ln(x);
                    108:        x = float128_mul(x, float128_ln2inv2);
                    109:        return x;
                    110: }
                    111: 
                    112: static float128 poly_l2p1(float128 x)
                    113: {
                    114:        /* using float128 for approximation */
                    115:        float128 x_p2 = float128_add(x, float128_two);
                    116:        x = float128_div(x, x_p2);
                    117:        x = poly_ln(x);
                    118:        x = float128_mul(x, float128_ln2inv2);
                    119:        return x;
                    120: }
                    121: 
                    122: // =================================================
                    123: // FYL2X                   Compute y * log (x)
                    124: //                                        2
                    125: // =================================================
                    126: 
                    127: //
                    128: // Uses the following identities:
                    129: //
                    130: // 1. ----------------------------------------------------------
                    131: //              ln(x)
                    132: //   log (x) = -------,  ln (x*y) = ln(x) + ln(y)
                    133: //      2       ln(2)
                    134: //
                    135: // 2. ----------------------------------------------------------
                    136: //                1+u             x-1
                    137: //   ln (x) = ln -----, when u = -----
                    138: //                1-u             x+1
                    139: //
                    140: // 3. ----------------------------------------------------------
                    141: //                        3     5     7           2n+1
                    142: //       1+u             u     u     u           u
                    143: //   ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ]
                    144: //       1-u             3     5     7           2n+1
                    145: //
                    146: 
                    147: static floatx80 fyl2x(floatx80 a, floatx80 b)
                    148: {
                    149:        uint64_t aSig = extractFloatx80Frac(a);
                    150:        int32_t aExp = extractFloatx80Exp(a);
                    151:        int aSign = extractFloatx80Sign(a);
                    152:        uint64_t bSig = extractFloatx80Frac(b);
                    153:        int32_t bExp = extractFloatx80Exp(b);
                    154:        int bSign = extractFloatx80Sign(b);
                    155: 
                    156:        int zSign = bSign ^ 1;
                    157: 
                    158:        if (aExp == 0x7FFF) {
                    159:                if ((uint64_t) (aSig<<1)
                    160:                                || ((bExp == 0x7FFF) && (uint64_t) (bSig<<1)))
                    161:                {
                    162:                        return propagateFloatx80NaN(a, b);
                    163:                }
                    164:                if (aSign)
                    165:                {
                    166: invalid:
                    167:                        float_raise(float_flag_invalid);
                    168:                        return floatx80_default_nan;
                    169:                }
                    170:                else {
                    171:                        if (bExp == 0) {
                    172:                                if (bSig == 0) goto invalid;
                    173:                                float_raise(float_flag_denormal);
                    174:                        }
                    175:                        return packFloatx80(bSign, 0x7FFF, floatx80_default_infinity_low);
                    176:                }
                    177:        }
                    178:        if (bExp == 0x7FFF)
                    179:        {
                    180:                if ((uint64_t) (bSig<<1)) return propagateFloatx80NaN(a, b);
                    181:                if (aSign && (uint64_t)(aExp | aSig)) goto invalid;
                    182:                if (aSig && (aExp == 0))
                    183:                        float_raise(float_flag_denormal);
                    184:                if (aExp < 0x3FFF) {
                    185:                        return packFloatx80(zSign, 0x7FFF, floatx80_default_infinity_low);
                    186:                }
                    187:                if (aExp == 0x3FFF && ((uint64_t) (aSig<<1) == 0)) goto invalid;
                    188:                return packFloatx80(bSign, 0x7FFF, floatx80_default_infinity_low);
                    189:        }
                    190:        if (aExp == 0) {
                    191:                if (aSig == 0) {
                    192:                        if ((bExp | bSig) == 0) goto invalid;
                    193:                        float_raise(float_flag_divbyzero);
                    194:                        return packFloatx80(zSign, 0x7FFF, floatx80_default_infinity_low);
                    195:                }
                    196:                if (aSign) goto invalid;
                    197:                float_raise(float_flag_denormal);
                    198:                normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
                    199:        }
                    200:        if (aSign) goto invalid;
                    201:        if (bExp == 0) {
                    202:                if (bSig == 0) {
                    203:                        if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0);
                    204:                        return packFloatx80(bSign, 0, 0);
                    205:                }
                    206:                float_raise(float_flag_denormal);
                    207:                normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
                    208:        }
                    209:        if (aExp == 0x3FFF && ((uint64_t) (aSig<<1) == 0))
                    210:                return packFloatx80(bSign, 0, 0);
                    211: 
                    212:        float_raise(float_flag_inexact);
                    213: 
                    214:        int ExpDiff = aExp - 0x3FFF;
                    215:        aExp = 0;
                    216:        if (aSig >= SQRT2_HALF_SIG) {
                    217:                ExpDiff++;
                    218:                aExp--;
                    219:        }
                    220: 
                    221:        /* ******************************** */
                    222:        /* using float128 for approximation */
                    223:        /* ******************************** */
                    224: 
                    225:        uint64_t zSig0, zSig1;
                    226:        shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
                    227:        float128 x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1);
                    228:        x = poly_l2(x);
                    229:        x = float128_add(x, int64_to_float128((int64_t) ExpDiff));
                    230:        return floatx80_mul(b, float128_to_floatx80(x));
                    231: }
                    232: 
                    233: // =================================================
                    234: // FYL2XP1                 Compute y * log (x + 1)
                    235: //                                        2
                    236: // =================================================
                    237: 
                    238: //
                    239: // Uses the following identities:
                    240: //
                    241: // 1. ----------------------------------------------------------
                    242: //              ln(x)
                    243: //   log (x) = -------
                    244: //      2       ln(2)
                    245: //
                    246: // 2. ----------------------------------------------------------
                    247: //                  1+u              x
                    248: //   ln (x+1) = ln -----, when u = -----
                    249: //                  1-u             x+2
                    250: //
                    251: // 3. ----------------------------------------------------------
                    252: //                        3     5     7           2n+1
                    253: //       1+u             u     u     u           u
                    254: //   ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ]
                    255: //       1-u             3     5     7           2n+1
                    256: //
                    257: 
                    258: floatx80 fyl2xp1(floatx80 a, floatx80 b)
                    259: {
                    260:        int32_t aExp, bExp;
                    261:        uint64_t aSig, bSig, zSig0, zSig1, zSig2;
                    262:        int aSign, bSign;
                    263: 
                    264:        aSig = extractFloatx80Frac(a);
                    265:        aExp = extractFloatx80Exp(a);
                    266:        aSign = extractFloatx80Sign(a);
                    267:        bSig = extractFloatx80Frac(b);
                    268:        bExp = extractFloatx80Exp(b);
                    269:        bSign = extractFloatx80Sign(b);
                    270:        int zSign = aSign ^ bSign;
                    271: 
                    272:        if (aExp == 0x7FFF) {
                    273:                if ((uint64_t) (aSig<<1)
                    274:                                || ((bExp == 0x7FFF) && (uint64_t) (bSig<<1)))
                    275:                {
                    276:                        return propagateFloatx80NaN(a, b);
                    277:                }
                    278:                if (aSign)
                    279:                {
                    280: invalid:
                    281:                        float_raise(float_flag_invalid);
                    282:                        return floatx80_default_nan;
                    283:                }
                    284:                        else {
                    285:                        if (bExp == 0) {
                    286:                                if (bSig == 0) goto invalid;
                    287:                                float_raise(float_flag_denormal);
                    288:                        }
                    289:                        return packFloatx80(bSign, 0x7FFF, floatx80_default_infinity_low);
                    290:                }
                    291:        }
                    292:        if (bExp == 0x7FFF)
                    293:        {
                    294:                if ((uint64_t) (bSig<<1))
                    295:                        return propagateFloatx80NaN(a, b);
                    296: 
                    297:                if (aExp == 0) {
                    298:                        if (aSig == 0) goto invalid;
                    299:                        float_raise(float_flag_denormal);
                    300:                }
                    301: 
                    302:                return packFloatx80(zSign, 0x7FFF, floatx80_default_infinity_low);
                    303:        }
                    304:        if (aExp == 0) {
                    305:                if (aSig == 0) {
                    306:                        if (bSig && (bExp == 0)) float_raise(float_flag_denormal);
                    307:                        return packFloatx80(zSign, 0, 0);
                    308:                }
                    309:                float_raise(float_flag_denormal);
                    310:                normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
                    311:        }
                    312:        if (bExp == 0) {
                    313:                if (bSig == 0) return packFloatx80(zSign, 0, 0);
                    314:                float_raise(float_flag_denormal);
                    315:                normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
                    316:        }
                    317: 
                    318:        float_raise(float_flag_inexact);
                    319: 
                    320:        if (aSign && aExp >= 0x3FFF)
                    321:                return a;
                    322: 
                    323:        if (aExp >= 0x3FFC) // big argument
                    324:        {
                    325:                return fyl2x(floatx80_add(a, floatx80_one), b);
                    326:        }
                    327: 
                    328:        // handle tiny argument
                    329:        if (aExp < EXP_BIAS-70)
                    330:        {
                    331:                // first order approximation, return (a*b)/ln(2)
                    332:                int32_t zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE;
                    333: 
                    334:        mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2);
                    335:                if (0 < (int64_t) zSig0) {
                    336:                        shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
                    337:                        --zExp;
                    338:                }
                    339: 
                    340:                zExp = zExp + bExp - 0x3FFE;
                    341:        mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2);
                    342:                if (0 < (int64_t) zSig0) {
                    343:                        shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
                    344:                        --zExp;
                    345:                }
                    346: 
                    347:                return
                    348:                        roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1);
                    349:        }
                    350: 
                    351:        /* ******************************** */
                    352:        /* using float128 for approximation */
                    353:        /* ******************************** */
                    354: 
                    355:        shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
                    356:        float128 x = packFloat128(aSign, aExp, zSig0, zSig1);
                    357:        x = poly_l2p1(x);
                    358:        return floatx80_mul(b, float128_to_floatx80(x));
                    359: }
                    360: 
                    361: floatx80 floatx80_flognp1(floatx80 a)
                    362: {
                    363:        return fyl2xp1(a, floatx80_ln_2);
                    364: }
                    365: 
                    366: floatx80 floatx80_flogn(floatx80 a)
                    367: {
                    368:        return fyl2x(a, floatx80_ln_2);
                    369: }
                    370: 
                    371: floatx80 floatx80_flog2(floatx80 a)
                    372: {
                    373:        return fyl2x(a, floatx80_one);
                    374: }
                    375: 
                    376: floatx80 floatx80_flog10(floatx80 a)
                    377: {
                    378:        return fyl2x(a, floatx80_log10_2);
                    379: }

unix.superglobalmegacorp.com

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