Annotation of previous/src/softfloat/softfloat_fpsp.c, revision 1.1

1.1     ! root        1: 
        !             2: /*============================================================================
        !             3: 
        !             4:  This C source file is an extension to the SoftFloat IEC/IEEE Floating-point
        !             5:  Arithmetic Package, Release 2a.
        !             6: 
        !             7:  Written by Andreas Grabher for Previous, NeXT Computer Emulator.
        !             8:  
        !             9: =============================================================================*/
        !            10: 
        !            11: #include "softfloat.h"
        !            12: #include "softfloat_fpsp_tables.h"
        !            13: 
        !            14: 
        !            15: /*----------------------------------------------------------------------------
        !            16: | Algorithms for transcendental functions supported by MC68881 and MC68882 
        !            17: | mathematical coprocessors. The functions are derived from FPSP library.
        !            18: *----------------------------------------------------------------------------*/
        !            19: 
        !            20: #define pi_sig      LIT64(0xc90fdaa22168c235)
        !            21: #define pi_sig0     LIT64(0xc90fdaa22168c234)
        !            22: #define pi_sig1     LIT64(0xc4c6628b80dc1cd1)
        !            23: 
        !            24: #define pi_exp      0x4000
        !            25: #define piby2_exp   0x3FFF
        !            26: #define piby4_exp   0x3FFE
        !            27: 
        !            28: #define one_exp     0x3FFF
        !            29: #define one_sig     LIT64(0x8000000000000000)
        !            30: 
        !            31: 
        !            32: /*----------------------------------------------------------------------------
        !            33:  | Function for compactifying extended double-precision floating point values.
        !            34:  *----------------------------------------------------------------------------*/
        !            35: 
        !            36: int32 floatx80_make_compact(int32 aExp, bits64 aSig)
        !            37: {
        !            38:     return (aExp<<16)|(aSig>>48);
        !            39: }
        !            40: 
        !            41: 
        !            42: /*----------------------------------------------------------------------------
        !            43:  | Arc cosine
        !            44:  *----------------------------------------------------------------------------*/
        !            45: 
        !            46: floatx80 floatx80_acos(floatx80 a)
        !            47: {
        !            48:     flag aSign;
        !            49:     int32 aExp;
        !            50:     bits64 aSig;
        !            51:     
        !            52:     int8 user_rnd_mode, user_rnd_prec;
        !            53:     
        !            54:     int32 compact;
        !            55:     floatx80 fp0, fp1, one;
        !            56:     
        !            57:     aSig = extractFloatx80Frac(a);
        !            58:     aExp = extractFloatx80Exp(a);
        !            59:     aSign = extractFloatx80Sign(a);
        !            60:     
        !            61:     if (aExp == 0x7FFF && (bits64) (aSig<<1)) {
        !            62:         return propagateFloatx80NaNOneArg(a);
        !            63:     }
        !            64:     if (aExp == 0 && aSig == 0) {
        !            65:         float_raise(float_flag_inexact);
        !            66:         return roundAndPackFloatx80(floatx80_rounding_precision, 0, piby2_exp, pi_sig, 0);
        !            67:     }
        !            68: 
        !            69:     compact = floatx80_make_compact(aExp, aSig);
        !            70:     
        !            71:     if (compact >= 0x3FFF8000) { // |X| >= 1
        !            72:         if (aExp == one_exp && aSig == one_sig) { // |X| == 1
        !            73:             if (aSign) { // X == -1
        !            74:                 a = packFloatx80(0, pi_exp, pi_sig);
        !            75:                 float_raise(float_flag_inexact);
        !            76:                 return floatx80_move(a);
        !            77:             } else { // X == +1
        !            78:                 return packFloatx80(0, 0, 0);
        !            79:             }
        !            80:         } else { // |X| > 1
        !            81:             float_raise(float_flag_invalid);
        !            82:             a.low = floatx80_default_nan_low;
        !            83:             a.high = floatx80_default_nan_high;
        !            84:             return a;
        !            85:         }
        !            86:     } // |X| < 1
        !            87:     
        !            88:     user_rnd_mode = float_rounding_mode;
        !            89:     user_rnd_prec = floatx80_rounding_precision;
        !            90:     float_rounding_mode = float_round_nearest_even;
        !            91:     floatx80_rounding_precision = 80;
        !            92:     
        !            93:     one = packFloatx80(0, one_exp, one_sig);
        !            94:     fp0 = a;
        !            95:     
        !            96:     fp1 = floatx80_add(one, fp0);   // 1 + X
        !            97:     fp0 = floatx80_sub(one, fp0);   // 1 - X
        !            98:     fp0 = floatx80_div(fp0, fp1);   // (1-X)/(1+X)
        !            99:     fp0 = floatx80_sqrt(fp0);       // SQRT((1-X)/(1+X))
        !           100:     fp0 = floatx80_atan(fp0);       // ATAN(SQRT((1-X)/(1+X)))
        !           101:     
        !           102:     float_rounding_mode = user_rnd_mode;
        !           103:     floatx80_rounding_precision = user_rnd_prec;
        !           104:     
        !           105:     a = floatx80_add(fp0, fp0);     // 2 * ATAN(SQRT((1-X)/(1+X)))
        !           106:     
        !           107:     float_raise(float_flag_inexact);
        !           108:     
        !           109:     return a;
        !           110: }
        !           111: 
        !           112: /*----------------------------------------------------------------------------
        !           113:  | Arc sine
        !           114:  *----------------------------------------------------------------------------*/
        !           115: 
        !           116: floatx80 floatx80_asin(floatx80 a)
        !           117: {
        !           118:     flag aSign;
        !           119:     int32 aExp;
        !           120:     bits64 aSig;
        !           121:     
        !           122:     int8 user_rnd_mode, user_rnd_prec;
        !           123:     
        !           124:     int32 compact;
        !           125:     floatx80 fp0, fp1, fp2, one;
        !           126:     
        !           127:     aSig = extractFloatx80Frac(a);
        !           128:     aExp = extractFloatx80Exp(a);
        !           129:     aSign = extractFloatx80Sign(a);
        !           130:     
        !           131:     if (aExp == 0x7FFF && (bits64) (aSig<<1)) {
        !           132:         return propagateFloatx80NaNOneArg(a);
        !           133:     }
        !           134:     
        !           135:     if (aExp == 0 && aSig == 0) {
        !           136:         return packFloatx80(aSign, 0, 0);
        !           137:     }
        !           138: 
        !           139:     compact = floatx80_make_compact(aExp, aSig);
        !           140:     
        !           141:     if (compact >= 0x3FFF8000) { // |X| >= 1
        !           142:         if (aExp == one_exp && aSig == one_sig) { // |X| == 1
        !           143:             float_raise(float_flag_inexact);
        !           144:             a = packFloatx80(aSign, piby2_exp, pi_sig);
        !           145:             return floatx80_move(a);
        !           146:         } else { // |X| > 1
        !           147:             float_raise(float_flag_invalid);
        !           148:             a.low = floatx80_default_nan_low;
        !           149:             a.high = floatx80_default_nan_high;
        !           150:             return a;
        !           151:         }
        !           152: 
        !           153:     } // |X| < 1
        !           154:     
        !           155:     user_rnd_mode = float_rounding_mode;
        !           156:     user_rnd_prec = floatx80_rounding_precision;
        !           157:     float_rounding_mode = float_round_nearest_even;
        !           158:     floatx80_rounding_precision = 80;
        !           159:     
        !           160:     one = packFloatx80(0, one_exp, one_sig);
        !           161:     fp0 = a;
        !           162: 
        !           163:     fp1 = floatx80_sub(one, fp0);   // 1 - X
        !           164:     fp2 = floatx80_add(one, fp0);   // 1 + X
        !           165:     fp1 = floatx80_mul(fp2, fp1);   // (1+X)*(1-X)
        !           166:     fp1 = floatx80_sqrt(fp1);       // SQRT((1+X)*(1-X))
        !           167:     fp0 = floatx80_div(fp0, fp1);   // X/SQRT((1+X)*(1-X))
        !           168:     
        !           169:     float_rounding_mode = user_rnd_mode;
        !           170:     floatx80_rounding_precision = user_rnd_prec;
        !           171:     
        !           172:     a = floatx80_atan(fp0);         // ATAN(X/SQRT((1+X)*(1-X)))
        !           173:     
        !           174:     float_raise(float_flag_inexact);
        !           175: 
        !           176:     return a;
        !           177: }
        !           178: 
        !           179: /*----------------------------------------------------------------------------
        !           180:  | Arc tangent
        !           181:  *----------------------------------------------------------------------------*/
        !           182: 
        !           183: floatx80 floatx80_atan(floatx80 a)
        !           184: {
        !           185:     flag aSign;
        !           186:     int32 aExp;
        !           187:     bits64 aSig;
        !           188:     
        !           189:     int8 user_rnd_mode, user_rnd_prec;
        !           190:     
        !           191:     int32 compact, tbl_index;
        !           192:     floatx80 fp0, fp1, fp2, fp3, xsave;
        !           193: 
        !           194:     aSig = extractFloatx80Frac(a);
        !           195:     aExp = extractFloatx80Exp(a);
        !           196:     aSign = extractFloatx80Sign(a);
        !           197:     
        !           198:     if (aExp == 0x7FFF) {
        !           199:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a);
        !           200:         a = packFloatx80(aSign, piby2_exp, pi_sig);
        !           201:         float_raise(float_flag_inexact);
        !           202:         return floatx80_move(a);
        !           203:     }
        !           204:     
        !           205:     if (aExp == 0 && aSig == 0) {
        !           206:         return packFloatx80(aSign, 0, 0);
        !           207:     }
        !           208:     
        !           209:     compact = floatx80_make_compact(aExp, aSig);
        !           210:     
        !           211:     user_rnd_mode = float_rounding_mode;
        !           212:     user_rnd_prec = floatx80_rounding_precision;
        !           213:     float_rounding_mode = float_round_nearest_even;
        !           214:     floatx80_rounding_precision = 80;
        !           215: 
        !           216:     if (compact < 0x3FFB8000 || compact > 0x4002FFFF) { // |X| >= 16 or |X| < 1/16
        !           217:         if (compact > 0x3FFF8000) { // |X| >= 16
        !           218:             if (compact > 0x40638000) { // |X| > 2^(100)
        !           219:                 fp0 = packFloatx80(aSign, piby2_exp, pi_sig);
        !           220:                 fp1 = packFloatx80(aSign, 0x0001, one_sig);
        !           221:                 
        !           222:                 float_rounding_mode = user_rnd_mode;
        !           223:                 floatx80_rounding_precision = user_rnd_prec;
        !           224:                 
        !           225:                 a = floatx80_sub(fp0, fp1);
        !           226:                 
        !           227:                 float_raise(float_flag_inexact);
        !           228:                 
        !           229:                 return a;
        !           230:             } else {
        !           231:                 fp0 = a;
        !           232:                 fp1 = packFloatx80(1, one_exp, one_sig); // -1
        !           233:                 fp1 = floatx80_div(fp1, fp0); // X' = -1/X
        !           234:                 xsave = fp1;
        !           235:                 fp0 = floatx80_mul(fp1, fp1); // Y = X'*X'
        !           236:                 fp1 = floatx80_mul(fp0, fp0); // Z = Y*Y
        !           237:                 fp3 = float64_to_floatx80(LIT64(0xBFB70BF398539E6A)); // C5
        !           238:                 fp2 = float64_to_floatx80(LIT64(0x3FBC7187962D1D7D)); // C4
        !           239:                 fp3 = floatx80_mul(fp3, fp1); // Z*C5
        !           240:                 fp2 = floatx80_mul(fp2, fp1); // Z*C4
        !           241:                 fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBFC24924827107B8))); // C3+Z*C5
        !           242:                 fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC999999996263E))); // C2+Z*C4
        !           243:                 fp1 = floatx80_mul(fp1, fp3); // Z*(C3+Z*C5)
        !           244:                 fp2 = floatx80_mul(fp2, fp0); // Y*(C2+Z*C4)
        !           245:                 fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0xBFD5555555555536))); // C1+Z*(C3+Z*C5)
        !           246:                 fp0 = floatx80_mul(fp0, xsave); // X'*Y
        !           247:                 fp1 = floatx80_add(fp1, fp2); // [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)]
        !           248:                 fp0 = floatx80_mul(fp0, fp1); // X'*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]) ??
        !           249:                 fp0 = floatx80_add(fp0, xsave);
        !           250:                 fp1 = packFloatx80(aSign, piby2_exp, pi_sig);
        !           251:                 
        !           252:                 float_rounding_mode = user_rnd_mode;
        !           253:                 floatx80_rounding_precision = user_rnd_prec;
        !           254: 
        !           255:                 a = floatx80_add(fp0, fp1);
        !           256:                 
        !           257:                 float_raise(float_flag_inexact);
        !           258:                 
        !           259:                 return a;
        !           260:             }
        !           261:         } else { // |X| < 1/16
        !           262:             if (compact < 0x3FD78000) { // |X| < 2^(-40)
        !           263:                 float_rounding_mode = user_rnd_mode;
        !           264:                 floatx80_rounding_precision = user_rnd_prec;
        !           265:                 
        !           266:                 a = floatx80_move(a);
        !           267:                 
        !           268:                 float_raise(float_flag_inexact);
        !           269:                 
        !           270:                 return a;
        !           271:             } else {
        !           272:                 fp0 = a;
        !           273:                 xsave = a;
        !           274:                 fp0 = floatx80_mul(fp0, fp0); // Y = X*X
        !           275:                 fp1 = floatx80_mul(fp0, fp0); // Z = Y*Y
        !           276:                 fp2 = float64_to_floatx80(LIT64(0x3FB344447F876989)); // B6
        !           277:                 fp3 = float64_to_floatx80(LIT64(0xBFB744EE7FAF45DB)); // B5
        !           278:                 fp2 = floatx80_mul(fp2, fp1); // Z*B6
        !           279:                 fp3 = floatx80_mul(fp3, fp1); // Z*B5
        !           280:                 fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FBC71C646940220))); // B4+Z*B6
        !           281:                 fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBFC24924921872F9))); // B3+Z*B5
        !           282:                 fp2 = floatx80_mul(fp2, fp1); // Z*(B4+Z*B6)
        !           283:                 fp1 = floatx80_mul(fp1, fp3); // Z*(B3+Z*B5)
        !           284:                 fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC9999999998FA9))); // B2+Z*(B4+Z*B6)
        !           285:                 fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0xBFD5555555555555))); // B1+Z*(B3+Z*B5)
        !           286:                 fp2 = floatx80_mul(fp2, fp0); // Y*(B2+Z*(B4+Z*B6))
        !           287:                 fp0 = floatx80_mul(fp0, xsave); // X*Y
        !           288:                 fp1 = floatx80_add(fp1, fp2); // [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]
        !           289:                 fp0 = floatx80_mul(fp0, fp1); // X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))])
        !           290:                 
        !           291:                 float_rounding_mode = user_rnd_mode;
        !           292:                 floatx80_rounding_precision = user_rnd_prec;
        !           293:                 
        !           294:                 a = floatx80_add(fp0, xsave);
        !           295:                 
        !           296:                 float_raise(float_flag_inexact);
        !           297:                 
        !           298:                 return a;
        !           299:             }
        !           300:         }
        !           301:     } else {
        !           302:         aSig &= LIT64(0xF800000000000000);
        !           303:         aSig |= LIT64(0x0400000000000000);
        !           304:         xsave = packFloatx80(aSign, aExp, aSig); // F
        !           305:         fp0 = a;
        !           306:         fp1 = a; // X
        !           307:         fp2 = packFloatx80(0, one_exp, one_sig); // 1
        !           308:         fp1 = floatx80_mul(fp1, xsave); // X*F
        !           309:         fp0 = floatx80_sub(fp0, xsave); // X-F
        !           310:         fp1 = floatx80_add(fp1, fp2); // 1 + X*F
        !           311:         fp0 = floatx80_div(fp0, fp1); // U = (X-F)/(1+X*F)
        !           312:         
        !           313:         tbl_index = compact;
        !           314:         
        !           315:         tbl_index &= 0x7FFF0000;
        !           316:         tbl_index -= 0x3FFB0000;
        !           317:         tbl_index >>= 1;
        !           318:         tbl_index += compact&0x00007800;
        !           319:         tbl_index >>= 11;
        !           320:         
        !           321:         fp3 = atan_tbl[tbl_index];
        !           322:         
        !           323:         fp3.high |= aSign ? 0x8000 : 0; // ATAN(F)
        !           324:         
        !           325:         fp1 = floatx80_mul(fp0, fp0); // V = U*U
        !           326:         fp2 = float64_to_floatx80(LIT64(0xBFF6687E314987D8)); // A3
        !           327:         fp2 = floatx80_add(fp2, fp1); // A3+V
        !           328:         fp2 = floatx80_mul(fp2, fp1); // V*(A3+V)
        !           329:         fp1 = floatx80_mul(fp1, fp0); // U*V
        !           330:         fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x4002AC6934A26DB3))); // A2+V*(A3+V)
        !           331:         fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0xBFC2476F4E1DA28E))); // A1+U*V
        !           332:         fp1 = floatx80_mul(fp1, fp2); // A1*U*V*(A2+V*(A3+V))
        !           333:         fp0 = floatx80_add(fp0, fp1); // ATAN(U)
        !           334:         
        !           335:         float_rounding_mode = user_rnd_mode;
        !           336:         floatx80_rounding_precision = user_rnd_prec;
        !           337:         
        !           338:         a = floatx80_add(fp0, fp3); // ATAN(X)
        !           339:         
        !           340:         float_raise(float_flag_inexact);
        !           341:         
        !           342:         return a;
        !           343:     }
        !           344: }
        !           345: 
        !           346: /*----------------------------------------------------------------------------
        !           347:  | Hyperbolic arc tangent
        !           348:  *----------------------------------------------------------------------------*/
        !           349: 
        !           350: floatx80 floatx80_atanh(floatx80 a)
        !           351: {
        !           352:     flag aSign;
        !           353:     int32 aExp;
        !           354:     bits64 aSig;
        !           355:     
        !           356:     int8 user_rnd_mode, user_rnd_prec;
        !           357:     
        !           358:     int32 compact;
        !           359:     floatx80 fp0, fp1, fp2, one;
        !           360: 
        !           361:     aSig = extractFloatx80Frac(a);
        !           362:     aExp = extractFloatx80Exp(a);
        !           363:     aSign = extractFloatx80Sign(a);
        !           364:     
        !           365:     if (aExp == 0x7FFF && (bits64) (aSig<<1)) {
        !           366:         return propagateFloatx80NaNOneArg(a);
        !           367:     }
        !           368:     
        !           369:     if (aExp == 0 && aSig == 0) {
        !           370:         return packFloatx80(aSign, 0, 0);
        !           371:     }
        !           372:     
        !           373:     compact = floatx80_make_compact(aExp, aSig);
        !           374:     
        !           375:     if (compact >= 0x3FFF8000) { // |X| >= 1
        !           376:         if (aExp == one_exp && aSig == one_sig) { // |X| == 1
        !           377:             float_raise(float_flag_divbyzero);
        !           378:             return packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low);
        !           379:         } else { // |X| > 1
        !           380:             float_raise(float_flag_invalid);
        !           381:             a.low = floatx80_default_nan_low;
        !           382:             a.high = floatx80_default_nan_high;
        !           383:             return a;
        !           384:         }
        !           385:     } // |X| < 1
        !           386:     
        !           387:     user_rnd_mode = float_rounding_mode;
        !           388:     user_rnd_prec = floatx80_rounding_precision;
        !           389:     float_rounding_mode = float_round_nearest_even;
        !           390:     floatx80_rounding_precision = 80;
        !           391:     
        !           392:     one = packFloatx80(0, one_exp, one_sig);
        !           393:     fp2 = packFloatx80(aSign, 0x3FFE, one_sig); // SIGN(X) * (1/2)
        !           394:     fp0 = packFloatx80(0, aExp, aSig); // Y = |X|
        !           395:     fp1 = packFloatx80(1, aExp, aSig); // -Y
        !           396:     fp0 = floatx80_add(fp0, fp0); // 2Y
        !           397:     fp1 = floatx80_add(fp1, one); // 1-Y
        !           398:     fp0 = floatx80_div(fp0, fp1); // Z = 2Y/(1-Y)
        !           399:     fp0 = floatx80_lognp1(fp0); // LOG1P(Z)
        !           400:     
        !           401:     float_rounding_mode = user_rnd_mode;
        !           402:     floatx80_rounding_precision = user_rnd_prec;
        !           403:     
        !           404:     a = floatx80_mul(fp0, fp2); // ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z)
        !           405:     
        !           406:     float_raise(float_flag_inexact);
        !           407:     
        !           408:     return a;
        !           409: }
        !           410: 
        !           411: /*----------------------------------------------------------------------------
        !           412:  | Cosine
        !           413:  *----------------------------------------------------------------------------*/
        !           414: 
        !           415: floatx80 floatx80_cos(floatx80 a)
        !           416: {
        !           417:     flag aSign, xSign;
        !           418:     int32 aExp, xExp;
        !           419:     bits64 aSig, xSig;
        !           420:     
        !           421:     int8 user_rnd_mode, user_rnd_prec;
        !           422:     
        !           423:     int32 compact, l, n, j;
        !           424:     floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
        !           425:     float32 posneg1, twoto63;
        !           426:     flag adjn, endflag;
        !           427:     
        !           428:     aSig = extractFloatx80Frac(a);
        !           429:     aExp = extractFloatx80Exp(a);
        !           430:     aSign = extractFloatx80Sign(a);
        !           431:     
        !           432:     if (aExp == 0x7FFF) {
        !           433:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a);
        !           434:         float_raise(float_flag_invalid);
        !           435:         a.low = floatx80_default_nan_low;
        !           436:         a.high = floatx80_default_nan_high;
        !           437:         return a;
        !           438:     }
        !           439:     
        !           440:     if (aExp == 0 && aSig == 0) {
        !           441:         return packFloatx80(0, one_exp, one_sig);
        !           442:     }
        !           443:     
        !           444:     adjn = 1;
        !           445:     
        !           446:     user_rnd_mode = float_rounding_mode;
        !           447:     user_rnd_prec = floatx80_rounding_precision;
        !           448:     float_rounding_mode = float_round_nearest_even;
        !           449:     floatx80_rounding_precision = 80;
        !           450:     
        !           451:     compact = floatx80_make_compact(aExp, aSig);
        !           452:     
        !           453:     fp0 = a;
        !           454:     
        !           455:     if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI
        !           456:         if (compact > 0x3FFF8000) { // |X| >= 15 PI
        !           457:             // REDUCEX
        !           458:             fp1 = packFloatx80(0, 0, 0);
        !           459:             if (compact == 0x7FFEFFFF) {
        !           460:                 twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000));
        !           461:                 twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000));
        !           462:                 fp0 = floatx80_add(fp0, twopi1);
        !           463:                 fp1 = fp0;
        !           464:                 fp0 = floatx80_add(fp0, twopi2);
        !           465:                 fp1 = floatx80_sub(fp1, fp0);
        !           466:                 fp1 = floatx80_add(fp1, twopi2);
        !           467:             }
        !           468:         loop:
        !           469:             xSign = extractFloatx80Sign(fp0);
        !           470:             xExp = extractFloatx80Exp(fp0);
        !           471:             xExp -= 0x3FFF;
        !           472:             if (xExp <= 28) {
        !           473:                 l = 0;
        !           474:                 endflag = 1;
        !           475:             } else {
        !           476:                 l = xExp - 27;
        !           477:                 endflag = 0;
        !           478:             }
        !           479:             invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI
        !           480:             twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000));
        !           481:             twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000));
        !           482:             
        !           483:             twoto63 = 0x5F000000;
        !           484:             twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL
        !           485:             
        !           486:             fp2 = floatx80_mul(fp0, invtwopi);
        !           487:             fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63)); // THE FRACTIONAL PART OF FP2 IS ROUNDED
        !           488:             fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63)); // FP2 is N
        !           489:             fp4 = floatx80_mul(twopi1, fp2); // W = N*P1
        !           490:             fp5 = floatx80_mul(twopi2, fp2); // w = N*P2
        !           491:             fp3 = floatx80_add(fp4, fp5); // FP3 is P
        !           492:             fp4 = floatx80_sub(fp4, fp3); // W-P
        !           493:             fp0 = floatx80_sub(fp0, fp3); // FP0 is A := R - P
        !           494:             fp4 = floatx80_add(fp4, fp5); // FP4 is p = (W-P)+w
        !           495:             fp3 = fp0; // FP3 is A
        !           496:             fp1 = floatx80_sub(fp1, fp4); // FP1 is a := r - p
        !           497:             fp0 = floatx80_add(fp0, fp1); // FP0 is R := A+a
        !           498:             
        !           499:             if (endflag > 0) {
        !           500:                 n = floatx80_to_int32(fp2);
        !           501:                 goto sincont;
        !           502:             }
        !           503:             fp3 = floatx80_sub(fp3, fp0); // A-R
        !           504:             fp1 = floatx80_add(fp1, fp3); // FP1 is r := (A-R)+a
        !           505:             goto loop;
        !           506:         } else {
        !           507:             // SINSM
        !           508:             fp0 = float32_to_floatx80(0x3F800000); // 1
        !           509:             
        !           510:             float_rounding_mode = user_rnd_mode;
        !           511:             floatx80_rounding_precision = user_rnd_prec;
        !           512:             
        !           513:             if (adjn) {
        !           514:                 // COSTINY
        !           515:                 a = floatx80_sub(fp0, float32_to_floatx80(0x00800000));
        !           516:             } else {
        !           517:                 // SINTINY
        !           518:                 a = floatx80_move(a);
        !           519:             }
        !           520:             float_raise(float_flag_inexact);
        !           521:             
        !           522:             return a;
        !           523:         }
        !           524:     } else {
        !           525:         fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883))); // X*2/PI
        !           526:         
        !           527:         n = floatx80_to_int32(fp1);
        !           528:         j = 32 + n;
        !           529:         
        !           530:         fp0 = floatx80_sub(fp0, pi_tbl[j]); // X-Y1
        !           531:         fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j])); // FP0 IS R = (X-Y1)-Y2
        !           532:         
        !           533:     sincont:
        !           534:         if ((n + adjn) & 1) {
        !           535:             // COSPOLY
        !           536:             fp0 = floatx80_mul(fp0, fp0); // FP0 IS S
        !           537:             fp1 = floatx80_mul(fp0, fp0); // FP1 IS T
        !           538:             fp2 = float64_to_floatx80(LIT64(0x3D2AC4D0D6011EE3)); // B8
        !           539:             fp3 = float64_to_floatx80(LIT64(0xBDA9396F9F45AC19)); // B7
        !           540:             
        !           541:             xSign = extractFloatx80Sign(fp0); // X IS S
        !           542:             xExp = extractFloatx80Exp(fp0);
        !           543:             xSig = extractFloatx80Frac(fp0);
        !           544:             
        !           545:             if (((n + adjn) >> 1) & 1) {
        !           546:                 xSign ^= 1;
        !           547:                 posneg1 = 0xBF800000; // -1
        !           548:             } else {
        !           549:                 xSign ^= 0;
        !           550:                 posneg1 = 0x3F800000; // 1
        !           551:             } // X IS NOW R'= SGN*R
        !           552:             
        !           553:             fp2 = floatx80_mul(fp2, fp1); // TB8
        !           554:             fp3 = floatx80_mul(fp3, fp1); // TB7
        !           555:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3E21EED90612C972))); // B6+TB8
        !           556:             fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE927E4FB79D9FCF))); // B5+TB7
        !           557:             fp2 = floatx80_mul(fp2, fp1); // T(B6+TB8)
        !           558:             fp3 = floatx80_mul(fp3, fp1); // T(B5+TB7)
        !           559:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A01A01D423))); // B4+T(B6+TB8)
        !           560:             fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438));
        !           561:             fp3 = floatx80_add(fp3, fp4); // B3+T(B5+TB7)
        !           562:             fp2 = floatx80_mul(fp2, fp1); // T(B4+T(B6+TB8))
        !           563:             fp1 = floatx80_mul(fp1, fp3); // T(B3+T(B5+TB7))
        !           564:             fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E));
        !           565:             fp2 = floatx80_add(fp2, fp4); // B2+T(B4+T(B6+TB8))
        !           566:             fp1 = floatx80_add(fp1, float32_to_floatx80(0xBF000000)); // B1+T(B3+T(B5+TB7))
        !           567:             fp0 = floatx80_mul(fp0, fp2); // S(B2+T(B4+T(B6+TB8)))
        !           568:             fp0 = floatx80_add(fp0, fp1); // [B1+T(B3+T(B5+TB7))]+[S(B2+T(B4+T(B6+TB8)))]
        !           569:             
        !           570:             x = packFloatx80(xSign, xExp, xSig);
        !           571:             fp0 = floatx80_mul(fp0, x);
        !           572:             
        !           573:             float_rounding_mode = user_rnd_mode;
        !           574:             floatx80_rounding_precision = user_rnd_prec;
        !           575:             
        !           576:             a = floatx80_add(fp0, float32_to_floatx80(posneg1));
        !           577:             
        !           578:             float_raise(float_flag_inexact);
        !           579:             
        !           580:             return a;
        !           581:         } else {
        !           582:             // SINPOLY
        !           583:             xSign = extractFloatx80Sign(fp0); // X IS R
        !           584:             xExp = extractFloatx80Exp(fp0);
        !           585:             xSig = extractFloatx80Frac(fp0);
        !           586:             
        !           587:             xSign ^= ((n + adjn) >> 1) & 1; // X IS NOW R'= SGN*R
        !           588:             
        !           589:             fp0 = floatx80_mul(fp0, fp0); // FP0 IS S
        !           590:             fp1 = floatx80_mul(fp0, fp0); // FP1 IS T
        !           591:             fp3 = float64_to_floatx80(LIT64(0xBD6AAA77CCC994F5)); // A7
        !           592:             fp2 = float64_to_floatx80(LIT64(0x3DE612097AAE8DA1)); // A6
        !           593:             fp3 = floatx80_mul(fp3, fp1); // T*A7
        !           594:             fp2 = floatx80_mul(fp2, fp1); // T*A6
        !           595:             fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE5AE6452A118AE4))); // A5+T*A7
        !           596:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EC71DE3A5341531))); // A4+T*A6
        !           597:             fp3 = floatx80_mul(fp3, fp1); // T(A5+TA7)
        !           598:             fp2 = floatx80_mul(fp2, fp1); // T(A4+TA6)
        !           599:             fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF2A01A01A018B59))); // A3+T(A5+TA7)
        !           600:             fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF));
        !           601:             fp2 = floatx80_add(fp2, fp4); // A2+T(A4+TA6)
        !           602:             fp1 = floatx80_mul(fp1, fp3); // T(A3+T(A5+TA7))
        !           603:             fp2 = floatx80_mul(fp2, fp0); // S(A2+T(A4+TA6))
        !           604:             fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99));
        !           605:             fp1 = floatx80_add(fp1, fp4); // A1+T(A3+T(A5+TA7))
        !           606:             fp1 = floatx80_add(fp1, fp2); // [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
        !           607:             
        !           608:             x = packFloatx80(xSign, xExp, xSig);
        !           609:             fp0 = floatx80_mul(fp0, x); // R'*S
        !           610:             fp0 = floatx80_mul(fp0, fp1); // SIN(R')-R'
        !           611:             
        !           612:             float_rounding_mode = user_rnd_mode;
        !           613:             floatx80_rounding_precision = user_rnd_prec;
        !           614:             
        !           615:             a = floatx80_add(fp0, x);
        !           616:             
        !           617:             float_raise(float_flag_inexact);
        !           618:             
        !           619:             return a;
        !           620:         }
        !           621:     }
        !           622: }
        !           623: 
        !           624: /*----------------------------------------------------------------------------
        !           625:  | Hyperbolic cosine
        !           626:  *----------------------------------------------------------------------------*/
        !           627: 
        !           628: floatx80 floatx80_cosh(floatx80 a)
        !           629: {
        !           630:     flag aSign;
        !           631:     int32 aExp;
        !           632:     bits64 aSig;
        !           633:     
        !           634:     int8 user_rnd_mode, user_rnd_prec;
        !           635:     
        !           636:     int32 compact;
        !           637:     floatx80 fp0, fp1;
        !           638:     
        !           639:     aSig = extractFloatx80Frac(a);
        !           640:     aExp = extractFloatx80Exp(a);
        !           641:     aSign = extractFloatx80Sign(a);
        !           642:     
        !           643:     if (aExp == 0x7FFF) {
        !           644:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a);
        !           645:         return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low);
        !           646:     }
        !           647:     
        !           648:     if (aExp == 0 && aSig == 0) {
        !           649:         return packFloatx80(0, one_exp, one_sig);
        !           650:     }
        !           651:     
        !           652:     user_rnd_mode = float_rounding_mode;
        !           653:     user_rnd_prec = floatx80_rounding_precision;
        !           654:     float_rounding_mode = float_round_nearest_even;
        !           655:     floatx80_rounding_precision = 80;
        !           656:     
        !           657:     compact = floatx80_make_compact(aExp, aSig);
        !           658:     
        !           659:     if (compact > 0x400CB167) {
        !           660:         if (compact > 0x400CB2B3) {
        !           661:             float_rounding_mode = user_rnd_mode;
        !           662:             floatx80_rounding_precision = user_rnd_prec;
        !           663:             return roundAndPackFloatx80(floatx80_rounding_precision, 0, 0x8000, one_sig, 0);
        !           664:         } else {
        !           665:             fp0 = packFloatx80(0, aExp, aSig);
        !           666:             fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x40C62D38D3D64634)));
        !           667:             fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x3D6F90AEB1E75CC7)));
        !           668:             fp0 = floatx80_etox(fp0);
        !           669:             fp1 = packFloatx80(0, 0x7FFB, one_sig);
        !           670:             
        !           671:             float_rounding_mode = user_rnd_mode;
        !           672:             floatx80_rounding_precision = user_rnd_prec;
        !           673: 
        !           674:             a = floatx80_mul(fp0, fp1);
        !           675:             
        !           676:             float_raise(float_flag_inexact);
        !           677:             
        !           678:             return a;
        !           679:         }
        !           680:     }
        !           681:     
        !           682:     fp0 = packFloatx80(0, aExp, aSig); // |X|
        !           683:     fp0 = floatx80_etox(fp0); // EXP(|X|)
        !           684:     fp0 = floatx80_mul(fp0, float32_to_floatx80(0x3F000000)); // (1/2)*EXP(|X|)
        !           685:     fp1 = float32_to_floatx80(0x3E800000); // 1/4
        !           686:     fp1 = floatx80_div(fp1, fp0); // 1/(2*EXP(|X|))
        !           687:     
        !           688:     float_rounding_mode = user_rnd_mode;
        !           689:     floatx80_rounding_precision = user_rnd_prec;
        !           690:     
        !           691:     a = floatx80_add(fp0, fp1);
        !           692:     
        !           693:     float_raise(float_flag_inexact);
        !           694:     
        !           695:     return a;
        !           696: }
        !           697: 
        !           698: /*----------------------------------------------------------------------------
        !           699:  | e to x
        !           700:  *----------------------------------------------------------------------------*/
        !           701: 
        !           702: floatx80 floatx80_etox(floatx80 a)
        !           703: {
        !           704:     flag aSign;
        !           705:     int32 aExp;
        !           706:     bits64 aSig;
        !           707:     
        !           708:     int8 user_rnd_mode, user_rnd_prec;
        !           709:     
        !           710:     int32 compact, n, j, k, m, m1;
        !           711:     floatx80 fp0, fp1, fp2, fp3, l2, scale, adjscale;
        !           712:     flag adjflag;
        !           713: 
        !           714:     aSig = extractFloatx80Frac(a);
        !           715:     aExp = extractFloatx80Exp(a);
        !           716:     aSign = extractFloatx80Sign(a);
        !           717:     
        !           718:     if (aExp == 0x7FFF) {
        !           719:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a);
        !           720:         if (aSign) return packFloatx80(0, 0, 0);
        !           721:         return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low);
        !           722:     }
        !           723:     
        !           724:     if (aExp == 0 && aSig == 0) {
        !           725:         return packFloatx80(0, one_exp, one_sig);
        !           726:     }
        !           727:     
        !           728:     user_rnd_mode = float_rounding_mode;
        !           729:     user_rnd_prec = floatx80_rounding_precision;
        !           730:     float_rounding_mode = float_round_nearest_even;
        !           731:     floatx80_rounding_precision = 80;
        !           732:     
        !           733:     adjflag = 0;
        !           734:     
        !           735:     if (aExp >= 0x3FBE) { // |X| >= 2^(-65)
        !           736:         compact = floatx80_make_compact(aExp, aSig);
        !           737:         
        !           738:         if (compact < 0x400CB167) { // |X| < 16380 log2
        !           739:             fp0 = a;
        !           740:             fp1 = a;
        !           741:             fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B)); // 64/log2 * X
        !           742:             adjflag = 0;
        !           743:             n = floatx80_to_int32(fp0); // int(64/log2*X)
        !           744:             fp0 = int32_to_floatx80(n);
        !           745:             
        !           746:             j = n & 0x3F; // J = N mod 64
        !           747:             m = n / 64; // NOTE: this is really arithmetic right shift by 6
        !           748:             if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity
        !           749:                 m--;
        !           750:             }
        !           751:             m += 0x3FFF; // biased exponent of 2^(M)
        !           752:             
        !           753:         expcont1:
        !           754:             fp2 = fp0; // N
        !           755:             fp0 = floatx80_mul(fp0, float32_to_floatx80(0xBC317218)); // N * L1, L1 = lead(-log2/64)
        !           756:             l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6));
        !           757:             fp2 = floatx80_mul(fp2, l2); // N * L2, L1+L2 = -log2/64
        !           758:             fp0 = floatx80_add(fp0, fp1); // X + N*L1
        !           759:             fp0 = floatx80_add(fp0, fp2); // R
        !           760:             
        !           761:             fp1 = floatx80_mul(fp0, fp0); // S = R*R
        !           762:             fp2 = float32_to_floatx80(0x3AB60B70); // A5
        !           763:             fp2 = floatx80_mul(fp2, fp1); // fp2 is S*A5
        !           764:             fp3 = floatx80_mul(float32_to_floatx80(0x3C088895), fp1); // fp3 is S*A4
        !           765:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554431))); // fp2 is A3+S*A5
        !           766:             fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554018))); // fp3 is A2+S*A4
        !           767:             fp2 = floatx80_mul(fp2, fp1); // fp2 is S*(A3+S*A5)
        !           768:             fp3 = floatx80_mul(fp3, fp1); // fp3 is S*(A2+S*A4)
        !           769:             fp2 = floatx80_add(fp2, float32_to_floatx80(0x3F000000)); // fp2 is A1+S*(A3+S*A5)
        !           770:             fp3 = floatx80_mul(fp3, fp0); // fp3 IS R*S*(A2+S*A4)
        !           771:             fp2 = floatx80_mul(fp2, fp1); // fp2 IS S*(A1+S*(A3+S*A5))
        !           772:             fp0 = floatx80_add(fp0, fp3); // fp0 IS R+R*S*(A2+S*A4)
        !           773:             fp0 = floatx80_add(fp0, fp2); // fp0 IS EXP(R) - 1
        !           774:             
        !           775:             fp1 = exp_tbl[j];
        !           776:             fp0 = floatx80_mul(fp0, fp1); // 2^(J/64)*(Exp(R)-1)
        !           777:             fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j])); // accurate 2^(J/64)
        !           778:             fp0 = floatx80_add(fp0, fp1); // 2^(J/64) + 2^(J/64)*(Exp(R)-1)
        !           779:             
        !           780:             scale = packFloatx80(0, m, one_sig);
        !           781:             if (adjflag) {
        !           782:                 adjscale = packFloatx80(0, m1, one_sig);
        !           783:                 fp0 = floatx80_mul(fp0, adjscale);
        !           784:             }
        !           785:             
        !           786:             float_rounding_mode = user_rnd_mode;
        !           787:             floatx80_rounding_precision = user_rnd_prec;
        !           788:             
        !           789:             a = floatx80_mul(fp0, scale);
        !           790:             
        !           791:             float_raise(float_flag_inexact);
        !           792:             
        !           793:             return a;
        !           794:         } else { // |X| >= 16380 log2
        !           795:             if (compact > 0x400CB27C) { // |X| >= 16480 log2
        !           796:                 float_rounding_mode = user_rnd_mode;
        !           797:                 floatx80_rounding_precision = user_rnd_prec;
        !           798:                 if (aSign) {
        !           799:                     a = roundAndPackFloatx80(floatx80_rounding_precision, 0, -0x1000, aSig, 0);
        !           800:                 } else {
        !           801:                     a = roundAndPackFloatx80(floatx80_rounding_precision, 0, 0x8000, aSig, 0);
        !           802:                 }
        !           803:                 float_raise(float_flag_inexact);
        !           804:                 
        !           805:                 return a;
        !           806:             } else {
        !           807:                 fp0 = a;
        !           808:                 fp1 = a;
        !           809:                 fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B)); // 64/log2 * X
        !           810:                 adjflag = 1;
        !           811:                 n = floatx80_to_int32(fp0); // int(64/log2*X)
        !           812:                 fp0 = int32_to_floatx80(n);
        !           813:                 
        !           814:                 j = n & 0x3F; // J = N mod 64
        !           815:                 k = n / 64; // NOTE: this is really arithmetic right shift by 6
        !           816:                 if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity
        !           817:                     k--;
        !           818:                 }
        !           819:                 m1 = k / 2; // NOTE: this is really arithmetic right shift by 1
        !           820:                 if (k < 0 && (k & 1)) { // arithmetic right shift is division and round towards minus infinity
        !           821:                     m1--;
        !           822:                 }
        !           823:                 m = k - m1;
        !           824:                 m1 += 0x3FFF; // biased exponent of 2^(M1)
        !           825:                 m += 0x3FFF; // biased exponent of 2^(M)
        !           826:                 
        !           827:                 goto expcont1;
        !           828:             }
        !           829:         }
        !           830:     } else { // |X| < 2^(-65)
        !           831:         float_rounding_mode = user_rnd_mode;
        !           832:         floatx80_rounding_precision = user_rnd_prec;
        !           833:         
        !           834:         a = floatx80_add(a, float32_to_floatx80(0x3F800000)); // 1 + X
        !           835:         
        !           836:         float_raise(float_flag_inexact);
        !           837:         
        !           838:         return a;
        !           839:     }
        !           840: }
        !           841: 
        !           842: /*----------------------------------------------------------------------------
        !           843:  | e to x minus 1
        !           844:  *----------------------------------------------------------------------------*/
        !           845: 
        !           846: floatx80 floatx80_etoxm1(floatx80 a)
        !           847: {
        !           848:     flag aSign;
        !           849:     int32 aExp;
        !           850:     bits64 aSig;
        !           851:     
        !           852:     int8 user_rnd_mode, user_rnd_prec;
        !           853:     
        !           854:     int32 compact, n, j, m, m1;
        !           855:     floatx80 fp0, fp1, fp2, fp3, l2, sc, onebysc;
        !           856:     
        !           857:     aSig = extractFloatx80Frac(a);
        !           858:     aExp = extractFloatx80Exp(a);
        !           859:     aSign = extractFloatx80Sign(a);
        !           860:     
        !           861:     if (aExp == 0x7FFF) {
        !           862:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a);
        !           863:         if (aSign) return packFloatx80(aSign, one_exp, one_sig);
        !           864:         return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low);
        !           865:     }
        !           866:     
        !           867:     if (aExp == 0 && aSig == 0) {
        !           868:         return packFloatx80(aSign, 0, 0);
        !           869:     }
        !           870:     
        !           871:     user_rnd_mode = float_rounding_mode;
        !           872:     user_rnd_prec = floatx80_rounding_precision;
        !           873:     float_rounding_mode = float_round_nearest_even;
        !           874:     floatx80_rounding_precision = 80;
        !           875:     
        !           876:     if (aExp >= 0x3FFD) { // |X| >= 1/4
        !           877:         compact = floatx80_make_compact(aExp, aSig);
        !           878:         
        !           879:         if (compact <= 0x4004C215) { // |X| <= 70 log2
        !           880:             fp0 = a;
        !           881:             fp1 = a;
        !           882:             fp0 = floatx80_mul(fp0, float32_to_floatx80(0x42B8AA3B)); // 64/log2 * X
        !           883:             n = floatx80_to_int32(fp0); // int(64/log2*X)
        !           884:             fp0 = int32_to_floatx80(n);
        !           885:             
        !           886:             j = n & 0x3F; // J = N mod 64
        !           887:             m = n / 64; // NOTE: this is really arithmetic right shift by 6
        !           888:             if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity
        !           889:                 m--;
        !           890:             }
        !           891:             m1 = -m;
        !           892:             //m += 0x3FFF; // biased exponent of 2^(M)
        !           893:             //m1 += 0x3FFF; // biased exponent of -2^(-M)
        !           894:             
        !           895:             fp2 = fp0; // N
        !           896:             fp0 = floatx80_mul(fp0, float32_to_floatx80(0xBC317218)); // N * L1, L1 = lead(-log2/64)
        !           897:             l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6));
        !           898:             fp2 = floatx80_mul(fp2, l2); // N * L2, L1+L2 = -log2/64
        !           899:             fp0 = floatx80_add(fp0, fp1); // X + N*L1
        !           900:             fp0 = floatx80_add(fp0, fp2); // R
        !           901:             
        !           902:             fp1 = floatx80_mul(fp0, fp0); // S = R*R
        !           903:             fp2 = float32_to_floatx80(0x3950097B); // A6
        !           904:             fp2 = floatx80_mul(fp2, fp1); // fp2 is S*A6
        !           905:             fp3 = floatx80_mul(float32_to_floatx80(0x3AB60B6A), fp1); // fp3 is S*A5
        !           906:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F81111111174385))); // fp2 IS A4+S*A6
        !           907:             fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FA5555555554F5A))); // fp3 is A3+S*A5
        !           908:             fp2 = floatx80_mul(fp2, fp1); // fp2 IS S*(A4+S*A6)
        !           909:             fp3 = floatx80_mul(fp3, fp1); // fp3 IS S*(A3+S*A5)
        !           910:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FC5555555555555))); // fp2 IS A2+S*(A4+S*A6)
        !           911:             fp3 = floatx80_add(fp3, float32_to_floatx80(0x3F000000)); // fp3 IS A1+S*(A3+S*A5)
        !           912:             fp2 = floatx80_mul(fp2, fp1); // fp2 IS S*(A2+S*(A4+S*A6))
        !           913:             fp1 = floatx80_mul(fp1, fp3); // fp1 IS S*(A1+S*(A3+S*A5))
        !           914:             fp2 = floatx80_mul(fp2, fp0); // fp2 IS R*S*(A2+S*(A4+S*A6))
        !           915:             fp0 = floatx80_add(fp0, fp1); // fp0 IS R+S*(A1+S*(A3+S*A5))
        !           916:             fp0 = floatx80_add(fp0, fp2); // fp0 IS EXP(R) - 1
        !           917:             
        !           918:             fp0 = floatx80_mul(fp0, exp_tbl[j]); // 2^(J/64)*(Exp(R)-1)
        !           919:             
        !           920:             if (m >= 64) {
        !           921:                 fp1 = float32_to_floatx80(exp_tbl2[j]);
        !           922:                 onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M)
        !           923:                 fp1 = floatx80_add(fp1, onebysc);
        !           924:                 fp0 = floatx80_add(fp0, fp1);
        !           925:                 fp0 = floatx80_add(fp0, exp_tbl[j]);
        !           926:             } else if (m < -3) {
        !           927:                 fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j]));
        !           928:                 fp0 = floatx80_add(fp0, exp_tbl[j]);
        !           929:                 onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M)
        !           930:                 fp0 = floatx80_add(fp0, onebysc);
        !           931:             } else { // -3 <= m <= 63
        !           932:                 fp1 = exp_tbl[j];
        !           933:                 fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j]));
        !           934:                 onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); // -2^(-M)
        !           935:                 fp1 = floatx80_add(fp1, onebysc);
        !           936:                 fp0 = floatx80_add(fp0, fp1);
        !           937:             }
        !           938:             
        !           939:             sc = packFloatx80(0, m + 0x3FFF, one_sig);
        !           940:             
        !           941:             float_rounding_mode = user_rnd_mode;
        !           942:             floatx80_rounding_precision = user_rnd_prec;
        !           943:             
        !           944:             a = floatx80_mul(fp0, sc);
        !           945:             
        !           946:             float_raise(float_flag_inexact);
        !           947:             
        !           948:             return a;
        !           949:         } else { // |X| > 70 log2
        !           950:             if (aSign) {
        !           951:                 fp0 = float32_to_floatx80(0xBF800000); // -1
        !           952:                 
        !           953:                 float_rounding_mode = user_rnd_mode;
        !           954:                 floatx80_rounding_precision = user_rnd_prec;
        !           955:                 
        !           956:                 a = floatx80_add(fp0, float32_to_floatx80(0x00800000)); // -1 + 2^(-126)
        !           957:                 
        !           958:                 float_raise(float_flag_inexact);
        !           959:                 
        !           960:                 return a;
        !           961:             } else {
        !           962:                 float_rounding_mode = user_rnd_mode;
        !           963:                 floatx80_rounding_precision = user_rnd_prec;
        !           964:                 
        !           965:                 return floatx80_etox(a);
        !           966:             }
        !           967:         }
        !           968:     } else { // |X| < 1/4
        !           969:         if (aExp >= 0x3FBE) {
        !           970:             fp0 = a;
        !           971:             fp0 = floatx80_mul(fp0, fp0); // S = X*X
        !           972:             fp1 = float32_to_floatx80(0x2F30CAA8); // B12
        !           973:             fp1 = floatx80_mul(fp1, fp0); // S * B12
        !           974:             fp2 = float32_to_floatx80(0x310F8290); // B11
        !           975:             fp1 = floatx80_add(fp1, float32_to_floatx80(0x32D73220)); // B10
        !           976:             fp2 = floatx80_mul(fp2, fp0);
        !           977:             fp1 = floatx80_mul(fp1, fp0);
        !           978:             fp2 = floatx80_add(fp2, float32_to_floatx80(0x3493F281)); // B9
        !           979:             fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3EC71DE3A5774682))); // B8
        !           980:             fp2 = floatx80_mul(fp2, fp0);
        !           981:             fp1 = floatx80_mul(fp1, fp0);
        !           982:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A019D7CB68))); // B7
        !           983:             fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3F2A01A01A019DF3))); // B6
        !           984:             fp2 = floatx80_mul(fp2, fp0);
        !           985:             fp1 = floatx80_mul(fp1, fp0);
        !           986:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F56C16C16C170E2))); // B5
        !           987:             fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3F81111111111111))); // B4
        !           988:             fp2 = floatx80_mul(fp2, fp0);
        !           989:             fp1 = floatx80_mul(fp1, fp0);
        !           990:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555555555))); // B3
        !           991:             fp3 = packFloatx80(0, 0x3FFC, LIT64(0xAAAAAAAAAAAAAAAB));
        !           992:             fp1 = floatx80_add(fp1, fp3); // B2
        !           993:             fp2 = floatx80_mul(fp2, fp0);
        !           994:             fp1 = floatx80_mul(fp1, fp0);
        !           995:             
        !           996:             fp2 = floatx80_mul(fp2, fp0);
        !           997:             fp1 = floatx80_mul(fp1, a);
        !           998:             
        !           999:             fp0 = floatx80_mul(fp0, float32_to_floatx80(0x3F000000)); // S*B1
        !          1000:             fp1 = floatx80_add(fp1, fp2); // Q
        !          1001:             fp0 = floatx80_add(fp0, fp1); // S*B1+Q
        !          1002:             
        !          1003:             float_rounding_mode = user_rnd_mode;
        !          1004:             floatx80_rounding_precision = user_rnd_prec;
        !          1005:             
        !          1006:             a = floatx80_add(fp0, a);
        !          1007:             
        !          1008:             float_raise(float_flag_inexact);
        !          1009:             
        !          1010:             return a;
        !          1011:         } else { // |X| < 2^(-65)
        !          1012:             sc = packFloatx80(1, 1, one_sig);
        !          1013:             fp0 = a;
        !          1014: 
        !          1015:             if (aExp < 0x0033) { // |X| < 2^(-16382)
        !          1016:                 fp0 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x48B0000000000000)));
        !          1017:                 fp0 = floatx80_add(fp0, sc);
        !          1018:                 
        !          1019:                 float_rounding_mode = user_rnd_mode;
        !          1020:                 floatx80_rounding_precision = user_rnd_prec;
        !          1021: 
        !          1022:                 a = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3730000000000000)));
        !          1023:             } else {
        !          1024:                 float_rounding_mode = user_rnd_mode;
        !          1025:                 floatx80_rounding_precision = user_rnd_prec;
        !          1026:                 
        !          1027:                 a = floatx80_add(fp0, sc);
        !          1028:             }
        !          1029:             
        !          1030:             float_raise(float_flag_inexact);
        !          1031:             
        !          1032:             return a;
        !          1033:         }
        !          1034:     }
        !          1035: }
        !          1036: 
        !          1037: /*----------------------------------------------------------------------------
        !          1038:  | Log base 10
        !          1039:  *----------------------------------------------------------------------------*/
        !          1040: 
        !          1041: floatx80 floatx80_log10(floatx80 a)
        !          1042: {
        !          1043:     flag aSign;
        !          1044:     int32 aExp;
        !          1045:     bits64 aSig;
        !          1046:     
        !          1047:     int8 user_rnd_mode, user_rnd_prec;
        !          1048:     
        !          1049:     floatx80 fp0, fp1;
        !          1050:     
        !          1051:     aSig = extractFloatx80Frac(a);
        !          1052:     aExp = extractFloatx80Exp(a);
        !          1053:     aSign = extractFloatx80Sign(a);
        !          1054:     
        !          1055:     if (aExp == 0x7FFF) {
        !          1056:         if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a);
        !          1057:         if (aSign == 0)
        !          1058:             return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low);
        !          1059:     }
        !          1060:     
        !          1061:     if (aExp == 0 && aSig == 0) {
        !          1062:         float_raise(float_flag_divbyzero);
        !          1063:         return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low);
        !          1064:     }
        !          1065:     
        !          1066:     if (aSign) {
        !          1067:         float_raise(float_flag_invalid);
        !          1068:         a.low = floatx80_default_nan_low;
        !          1069:         a.high = floatx80_default_nan_high;
        !          1070:         return a;
        !          1071:     }
        !          1072:     
        !          1073:     user_rnd_mode = float_rounding_mode;
        !          1074:     user_rnd_prec = floatx80_rounding_precision;
        !          1075:     float_rounding_mode = float_round_nearest_even;
        !          1076:     floatx80_rounding_precision = 80;
        !          1077:     
        !          1078:     fp0 = floatx80_logn(a);
        !          1079:     fp1 = packFloatx80(0, 0x3FFD, LIT64(0xDE5BD8A937287195)); // INV_L10
        !          1080:     
        !          1081:     float_rounding_mode = user_rnd_mode;
        !          1082:     floatx80_rounding_precision = user_rnd_prec;
        !          1083:     
        !          1084:     a = floatx80_mul(fp0, fp1); // LOGN(X)*INV_L10
        !          1085:     
        !          1086:     float_raise(float_flag_inexact);
        !          1087:     
        !          1088:     return a;
        !          1089: }
        !          1090: 
        !          1091: /*----------------------------------------------------------------------------
        !          1092:  | Log base 2
        !          1093:  *----------------------------------------------------------------------------*/
        !          1094: 
        !          1095: floatx80 floatx80_log2(floatx80 a)
        !          1096: {
        !          1097:     flag aSign;
        !          1098:     int32 aExp;
        !          1099:     bits64 aSig;
        !          1100:     
        !          1101:     int8 user_rnd_mode, user_rnd_prec;
        !          1102:     
        !          1103:     floatx80 fp0, fp1;
        !          1104:     
        !          1105:     aSig = extractFloatx80Frac(a);
        !          1106:     aExp = extractFloatx80Exp(a);
        !          1107:     aSign = extractFloatx80Sign(a);
        !          1108:     
        !          1109:     if (aExp == 0x7FFF) {
        !          1110:         if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a);
        !          1111:         if (aSign == 0)
        !          1112:             return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low);
        !          1113:     }
        !          1114:     
        !          1115:     if (aExp == 0) {
        !          1116:         if (aSig == 0) {
        !          1117:             float_raise(float_flag_divbyzero);
        !          1118:             return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low);
        !          1119:         }
        !          1120:         normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
        !          1121:     }
        !          1122:     
        !          1123:     if (aSign) {
        !          1124:         float_raise(float_flag_invalid);
        !          1125:         a.low = floatx80_default_nan_low;
        !          1126:         a.high = floatx80_default_nan_high;
        !          1127:         return a;
        !          1128:     }
        !          1129:     
        !          1130:     user_rnd_mode = float_rounding_mode;
        !          1131:     user_rnd_prec = floatx80_rounding_precision;
        !          1132:     float_rounding_mode = float_round_nearest_even;
        !          1133:     floatx80_rounding_precision = 80;
        !          1134:     
        !          1135:     if (aSig == one_sig) { // X is 2^k
        !          1136:         float_rounding_mode = user_rnd_mode;
        !          1137:         floatx80_rounding_precision = user_rnd_prec;
        !          1138:         
        !          1139:         a = int32_to_floatx80(aExp-0x3FFF);
        !          1140:     } else {
        !          1141:         fp0 = floatx80_logn(a);
        !          1142:         fp1 = packFloatx80(0, 0x3FFF, LIT64(0xB8AA3B295C17F0BC)); // INV_L2
        !          1143:         
        !          1144:         float_rounding_mode = user_rnd_mode;
        !          1145:         floatx80_rounding_precision = user_rnd_prec;
        !          1146:         
        !          1147:         a = floatx80_mul(fp0, fp1); // LOGN(X)*INV_L2
        !          1148:     }
        !          1149:     
        !          1150:     float_raise(float_flag_inexact);
        !          1151:     
        !          1152:     return a;
        !          1153: }
        !          1154: 
        !          1155: /*----------------------------------------------------------------------------
        !          1156:  | Log base e
        !          1157:  *----------------------------------------------------------------------------*/
        !          1158: 
        !          1159: floatx80 floatx80_logn(floatx80 a)
        !          1160: {
        !          1161:     flag aSign;
        !          1162:     int32 aExp;
        !          1163:     bits64 aSig, fSig;
        !          1164:     
        !          1165:     int8 user_rnd_mode, user_rnd_prec;
        !          1166:     
        !          1167:     int32 compact, j, k, adjk;
        !          1168:     floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu;
        !          1169:     
        !          1170:     aSig = extractFloatx80Frac(a);
        !          1171:     aExp = extractFloatx80Exp(a);
        !          1172:     aSign = extractFloatx80Sign(a);
        !          1173:     
        !          1174:     if (aExp == 0x7FFF) {
        !          1175:         if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a);
        !          1176:         if (aSign == 0)
        !          1177:             return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low);
        !          1178:     }
        !          1179:     
        !          1180:     adjk = 0;
        !          1181:     
        !          1182:     if (aExp == 0) {
        !          1183:         if (aSig == 0) { // zero
        !          1184:             float_raise(float_flag_divbyzero);
        !          1185:             return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low);
        !          1186:         }
        !          1187: #if 1
        !          1188:         if ((aSig & one_sig) == 0) { // denormal
        !          1189:             normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
        !          1190:             adjk = -100;
        !          1191:             aExp += 100;
        !          1192:             a = packFloatx80(aSign, aExp, aSig);
        !          1193:         }
        !          1194: #else
        !          1195:         normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
        !          1196: #endif
        !          1197:     }
        !          1198:     
        !          1199:     if (aSign) {
        !          1200:         float_raise(float_flag_invalid);
        !          1201:         a.low = floatx80_default_nan_low;
        !          1202:         a.high = floatx80_default_nan_high;
        !          1203:         return a;
        !          1204:     }
        !          1205:     
        !          1206:     user_rnd_mode = float_rounding_mode;
        !          1207:     user_rnd_prec = floatx80_rounding_precision;
        !          1208:     float_rounding_mode = float_round_nearest_even;
        !          1209:     floatx80_rounding_precision = 80;
        !          1210:     
        !          1211:     compact = floatx80_make_compact(aExp, aSig);
        !          1212:     
        !          1213:     if (compact < 0x3FFEF07D || compact > 0x3FFF8841) { // |X| < 15/16 or |X| > 17/16
        !          1214:         k = aExp - 0x3FFF;
        !          1215:         k += adjk;
        !          1216:         fp1 = int32_to_floatx80(k);
        !          1217:         
        !          1218:         fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000);
        !          1219:         j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F
        !          1220:         
        !          1221:         f = packFloatx80(0, 0x3FFF, fSig); // F
        !          1222:         fp0 = packFloatx80(0, 0x3FFF, aSig); // Y
        !          1223:         
        !          1224:         fp0 = floatx80_sub(fp0, f); // Y-F
        !          1225:         
        !          1226:         // LP1CONT1
        !          1227:         fp0 = floatx80_mul(fp0, log_tbl[j]); // FP0 IS U = (Y-F)/F
        !          1228:         logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC));
        !          1229:         klog2 = floatx80_mul(fp1, logof2); // FP1 IS K*LOG2
        !          1230:         fp2 = floatx80_mul(fp0, fp0); // FP2 IS V=U*U
        !          1231:         
        !          1232:         fp3 = fp2;
        !          1233:         fp1 = fp2;
        !          1234:         
        !          1235:         fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3FC2499AB5E4040B))); // V*A6
        !          1236:         fp2 = floatx80_mul(fp2, float64_to_floatx80(LIT64(0xBFC555B5848CB7DB))); // V*A5
        !          1237:         fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FC99999987D8730))); // A4+V*A6
        !          1238:         fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFCFFFFFFF6F7E97))); // A3+V*A5
        !          1239:         fp1 = floatx80_mul(fp1, fp3); // V*(A4+V*A6)
        !          1240:         fp2 = floatx80_mul(fp2, fp3); // V*(A3+V*A5)
        !          1241:         fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FD55555555555A4))); // A2+V*(A4+V*A6)
        !          1242:         fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFE0000000000008))); // A1+V*(A3+V*A5)
        !          1243:         fp1 = floatx80_mul(fp1, fp3); // V*(A2+V*(A4+V*A6))
        !          1244:         fp2 = floatx80_mul(fp2, fp3); // V*(A1+V*(A3+V*A5))
        !          1245:         fp1 = floatx80_mul(fp1, fp0); // U*V*(A2+V*(A4+V*A6))
        !          1246:         fp0 = floatx80_add(fp0, fp2); // U+V*(A1+V*(A3+V*A5))
        !          1247:         
        !          1248:         fp1 = floatx80_add(fp1, log_tbl[j+1]); // LOG(F)+U*V*(A2+V*(A4+V*A6))
        !          1249:         fp0 = floatx80_add(fp0, fp1); // FP0 IS LOG(F) + LOG(1+U)
        !          1250:         
        !          1251:         float_rounding_mode = user_rnd_mode;
        !          1252:         floatx80_rounding_precision = user_rnd_prec;
        !          1253:         
        !          1254:         a = floatx80_add(fp0, klog2);
        !          1255:         
        !          1256:         float_raise(float_flag_inexact);
        !          1257:         
        !          1258:         return a;
        !          1259:     } else { // |X-1| >= 1/16
        !          1260:         fp0 = a;
        !          1261:         fp1 = a;
        !          1262:         fp1 = floatx80_sub(fp1, float32_to_floatx80(0x3F800000)); // FP1 IS X-1
        !          1263:         fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // FP0 IS X+1
        !          1264:         fp1 = floatx80_add(fp1, fp1); // FP1 IS 2(X-1)
        !          1265:         
        !          1266:         // LP1CONT2
        !          1267:         fp1 = floatx80_div(fp1, fp0); // U
        !          1268:         saveu = fp1;
        !          1269:         fp0 = floatx80_mul(fp1, fp1); // FP0 IS V = U*U
        !          1270:         fp1 = floatx80_mul(fp0, fp0); // FP1 IS W = V*V
        !          1271:         
        !          1272:         fp3 = float64_to_floatx80(LIT64(0x3F175496ADD7DAD6)); // B5
        !          1273:         fp2 = float64_to_floatx80(LIT64(0x3F3C71C2FE80C7E0)); // B4
        !          1274:         fp3 = floatx80_mul(fp3, fp1); // W*B5
        !          1275:         fp2 = floatx80_mul(fp2, fp1); // W*B4
        !          1276:         fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3F624924928BCCFF))); // B3+W*B5
        !          1277:         fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F899999999995EC))); // B2+W*B4
        !          1278:         fp1 = floatx80_mul(fp1, fp3); // W*(B3+W*B5)
        !          1279:         fp2 = floatx80_mul(fp2, fp0); // V*(B2+W*B4)
        !          1280:         fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FB5555555555555))); // B1+W*(B3+W*B5)
        !          1281:         
        !          1282:         fp0 = floatx80_mul(fp0, saveu); // FP0 IS U*V
        !          1283:         fp1 = floatx80_add(fp1, fp2); // B1+W*(B3+W*B5) + V*(B2+W*B4)
        !          1284:         fp0 = floatx80_mul(fp0, fp1); // U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
        !          1285:         
        !          1286:         float_rounding_mode = user_rnd_mode;
        !          1287:         floatx80_rounding_precision = user_rnd_prec;
        !          1288:         
        !          1289:         a = floatx80_add(fp0, saveu);
        !          1290:         
        !          1291:         //if (!floatx80_is_zero(a)) {
        !          1292:             float_raise(float_flag_inexact);
        !          1293:         //}
        !          1294:         
        !          1295:         return a;
        !          1296:     }
        !          1297: }
        !          1298: 
        !          1299: /*----------------------------------------------------------------------------
        !          1300:  | Log base e of x plus 1
        !          1301:  *----------------------------------------------------------------------------*/
        !          1302: 
        !          1303: floatx80 floatx80_lognp1(floatx80 a)
        !          1304: {
        !          1305:     flag aSign;
        !          1306:     int32 aExp;
        !          1307:     bits64 aSig, fSig;
        !          1308:     
        !          1309:     int8 user_rnd_mode, user_rnd_prec;
        !          1310:     
        !          1311:     int32 compact, j, k;
        !          1312:     floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu;
        !          1313:     
        !          1314:     aSig = extractFloatx80Frac(a);
        !          1315:     aExp = extractFloatx80Exp(a);
        !          1316:     aSign = extractFloatx80Sign(a);
        !          1317:     
        !          1318:     if (aExp == 0x7FFF) {
        !          1319:         if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a);
        !          1320:         if (aSign) {
        !          1321:             float_raise(float_flag_invalid);
        !          1322:             a.low = floatx80_default_nan_low;
        !          1323:             a.high = floatx80_default_nan_high;
        !          1324:             return a;
        !          1325:         }
        !          1326:         return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low);
        !          1327:     }
        !          1328:     
        !          1329:     if (aExp == 0 && aSig == 0) {
        !          1330:         return packFloatx80(aSign, 0, 0);
        !          1331:     }
        !          1332:     
        !          1333:     if (aSign && aExp >= one_exp) {
        !          1334:         if (aExp == one_exp && aSig == one_sig) {
        !          1335:             float_raise(float_flag_divbyzero);
        !          1336:             packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low);
        !          1337:         }
        !          1338:         float_raise(float_flag_invalid);
        !          1339:         a.low = floatx80_default_nan_low;
        !          1340:         a.high = floatx80_default_nan_high;
        !          1341:         return a;
        !          1342:     }
        !          1343:     
        !          1344:     if (aExp < 0x3f99 || (aExp == 0x3f99 && aSig == one_sig)) { // <= min threshold
        !          1345:         float_raise(float_flag_inexact);
        !          1346:         return floatx80_move(a);
        !          1347:     }
        !          1348:     
        !          1349:     user_rnd_mode = float_rounding_mode;
        !          1350:     user_rnd_prec = floatx80_rounding_precision;
        !          1351:     float_rounding_mode = float_round_nearest_even;
        !          1352:     floatx80_rounding_precision = 80;
        !          1353:     
        !          1354:     compact = floatx80_make_compact(aExp, aSig);
        !          1355:     
        !          1356:     fp0 = a; // Z
        !          1357:     fp1 = a;
        !          1358:     
        !          1359:     fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // X = (1+Z)
        !          1360:     
        !          1361:     aExp = extractFloatx80Exp(fp0);
        !          1362:     aSig = extractFloatx80Frac(fp0);
        !          1363:     
        !          1364:     compact = floatx80_make_compact(aExp, aSig);
        !          1365:     
        !          1366:     if (compact < 0x3FFE8000 || compact > 0x3FFFC000) { // |X| < 1/2 or |X| > 3/2
        !          1367:         k = aExp - 0x3FFF;
        !          1368:         fp1 = int32_to_floatx80(k);
        !          1369:         
        !          1370:         fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000);
        !          1371:         j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F
        !          1372:         
        !          1373:         f = packFloatx80(0, 0x3FFF, fSig); // F
        !          1374:         fp0 = packFloatx80(0, 0x3FFF, aSig); // Y
        !          1375:         
        !          1376:         fp0 = floatx80_sub(fp0, f); // Y-F
        !          1377:         
        !          1378:     lp1cont1:
        !          1379:         // LP1CONT1
        !          1380:         fp0 = floatx80_mul(fp0, log_tbl[j]); // FP0 IS U = (Y-F)/F
        !          1381:         logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC));
        !          1382:         klog2 = floatx80_mul(fp1, logof2); // FP1 IS K*LOG2
        !          1383:         fp2 = floatx80_mul(fp0, fp0); // FP2 IS V=U*U
        !          1384:         
        !          1385:         fp3 = fp2;
        !          1386:         fp1 = fp2;
        !          1387:         
        !          1388:         fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3FC2499AB5E4040B))); // V*A6
        !          1389:         fp2 = floatx80_mul(fp2, float64_to_floatx80(LIT64(0xBFC555B5848CB7DB))); // V*A5
        !          1390:         fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FC99999987D8730))); // A4+V*A6
        !          1391:         fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFCFFFFFFF6F7E97))); // A3+V*A5
        !          1392:         fp1 = floatx80_mul(fp1, fp3); // V*(A4+V*A6)
        !          1393:         fp2 = floatx80_mul(fp2, fp3); // V*(A3+V*A5)
        !          1394:         fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FD55555555555A4))); // A2+V*(A4+V*A6)
        !          1395:         fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0xBFE0000000000008))); // A1+V*(A3+V*A5)
        !          1396:         fp1 = floatx80_mul(fp1, fp3); // V*(A2+V*(A4+V*A6))
        !          1397:         fp2 = floatx80_mul(fp2, fp3); // V*(A1+V*(A3+V*A5))
        !          1398:         fp1 = floatx80_mul(fp1, fp0); // U*V*(A2+V*(A4+V*A6))
        !          1399:         fp0 = floatx80_add(fp0, fp2); // U+V*(A1+V*(A3+V*A5))
        !          1400:         
        !          1401:         fp1 = floatx80_add(fp1, log_tbl[j+1]); // LOG(F)+U*V*(A2+V*(A4+V*A6))
        !          1402:         fp0 = floatx80_add(fp0, fp1); // FP0 IS LOG(F) + LOG(1+U)
        !          1403:         
        !          1404:         float_rounding_mode = user_rnd_mode;
        !          1405:         floatx80_rounding_precision = user_rnd_prec;
        !          1406:         
        !          1407:         a = floatx80_add(fp0, klog2);
        !          1408:         
        !          1409:         float_raise(float_flag_inexact);
        !          1410:         
        !          1411:         return a;
        !          1412:     } else if (compact < 0x3FFEF07D || compact > 0x3FFF8841) { // |X| < 1/16 or |X| > -1/16
        !          1413:         // LP1CARE
        !          1414:         fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000);
        !          1415:         f = packFloatx80(0, 0x3FFF, fSig); // F
        !          1416:         j = (fSig >> 56) & 0x7E; // DISPLACEMENT FOR 1/F
        !          1417: 
        !          1418:         if (compact >= 0x3FFF8000) { // 1+Z >= 1
        !          1419:             // KISZERO
        !          1420:             fp0 = floatx80_sub(float32_to_floatx80(0x3F800000), f); // 1-F
        !          1421:             fp0 = floatx80_add(fp0, fp1); // FP0 IS Y-F = (1-F)+Z
        !          1422:             fp1 = packFloatx80(0, 0, 0); // K = 0
        !          1423:         } else {
        !          1424:             // KISNEG
        !          1425:             fp0 = floatx80_sub(float32_to_floatx80(0x40000000), f); // 2-F
        !          1426:             fp1 = floatx80_add(fp1, fp1); // 2Z
        !          1427:             fp0 = floatx80_add(fp0, fp1); // FP0 IS Y-F = (2-F)+2Z
        !          1428:             fp1 = packFloatx80(1, one_exp, one_sig); // K = -1
        !          1429:         }
        !          1430:         goto lp1cont1;
        !          1431:     } else {
        !          1432:         // LP1ONE16
        !          1433:         fp1 = floatx80_add(fp1, fp1); // FP1 IS 2Z
        !          1434:         fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // FP0 IS 1+X
        !          1435:         
        !          1436:         // LP1CONT2
        !          1437:         fp1 = floatx80_div(fp1, fp0); // U
        !          1438:         saveu = fp1;
        !          1439:         fp0 = floatx80_mul(fp1, fp1); // FP0 IS V = U*U
        !          1440:         fp1 = floatx80_mul(fp0, fp0); // FP1 IS W = V*V
        !          1441:         
        !          1442:         fp3 = float64_to_floatx80(LIT64(0x3F175496ADD7DAD6)); // B5
        !          1443:         fp2 = float64_to_floatx80(LIT64(0x3F3C71C2FE80C7E0)); // B4
        !          1444:         fp3 = floatx80_mul(fp3, fp1); // W*B5
        !          1445:         fp2 = floatx80_mul(fp2, fp1); // W*B4
        !          1446:         fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3F624924928BCCFF))); // B3+W*B5
        !          1447:         fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3F899999999995EC))); // B2+W*B4
        !          1448:         fp1 = floatx80_mul(fp1, fp3); // W*(B3+W*B5)
        !          1449:         fp2 = floatx80_mul(fp2, fp0); // V*(B2+W*B4)
        !          1450:         fp1 = floatx80_add(fp1, float64_to_floatx80(LIT64(0x3FB5555555555555))); // B1+W*(B3+W*B5)
        !          1451:         
        !          1452:         fp0 = floatx80_mul(fp0, saveu); // FP0 IS U*V
        !          1453:         fp1 = floatx80_add(fp1, fp2); // B1+W*(B3+W*B5) + V*(B2+W*B4)
        !          1454:         fp0 = floatx80_mul(fp0, fp1); // U*V*( [B1+W*(B3+W*B5)] + [V*(B2+W*B4)] )
        !          1455:         
        !          1456:         float_rounding_mode = user_rnd_mode;
        !          1457:         floatx80_rounding_precision = user_rnd_prec;
        !          1458:         
        !          1459:         a = floatx80_add(fp0, saveu);
        !          1460:         
        !          1461:         //if (!floatx80_is_zero(a)) {
        !          1462:             float_raise(float_flag_inexact);
        !          1463:         //}
        !          1464:         
        !          1465:         return a;
        !          1466:     }
        !          1467: }
        !          1468: 
        !          1469: /*----------------------------------------------------------------------------
        !          1470:  | Sine
        !          1471:  *----------------------------------------------------------------------------*/
        !          1472: 
        !          1473: floatx80 floatx80_sin(floatx80 a)
        !          1474: {
        !          1475:     flag aSign, xSign;
        !          1476:     int32 aExp, xExp;
        !          1477:     bits64 aSig, xSig;
        !          1478:     
        !          1479:     int8 user_rnd_mode, user_rnd_prec;
        !          1480:     
        !          1481:     int32 compact, l, n, j;
        !          1482:     floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
        !          1483:     float32 posneg1, twoto63;
        !          1484:     flag adjn, endflag;
        !          1485: 
        !          1486:     aSig = extractFloatx80Frac(a);
        !          1487:     aExp = extractFloatx80Exp(a);
        !          1488:     aSign = extractFloatx80Sign(a);
        !          1489:     
        !          1490:     if (aExp == 0x7FFF) {
        !          1491:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a);
        !          1492:         float_raise(float_flag_invalid);
        !          1493:         a.low = floatx80_default_nan_low;
        !          1494:         a.high = floatx80_default_nan_high;
        !          1495:         return a;
        !          1496:     }
        !          1497:     
        !          1498:     if (aExp == 0 && aSig == 0) {
        !          1499:         return packFloatx80(aSign, 0, 0);
        !          1500:     }
        !          1501:     
        !          1502:     adjn = 0;
        !          1503:     
        !          1504:     user_rnd_mode = float_rounding_mode;
        !          1505:     user_rnd_prec = floatx80_rounding_precision;
        !          1506:     float_rounding_mode = float_round_nearest_even;
        !          1507:     floatx80_rounding_precision = 80;
        !          1508:     
        !          1509:     compact = floatx80_make_compact(aExp, aSig);
        !          1510:     
        !          1511:     fp0 = a;
        !          1512:     
        !          1513:     if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI
        !          1514:         if (compact > 0x3FFF8000) { // |X| >= 15 PI
        !          1515:             // REDUCEX
        !          1516:             fp1 = packFloatx80(0, 0, 0);
        !          1517:             if (compact == 0x7FFEFFFF) {
        !          1518:                 twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000));
        !          1519:                 twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000));
        !          1520:                 fp0 = floatx80_add(fp0, twopi1);
        !          1521:                 fp1 = fp0;
        !          1522:                 fp0 = floatx80_add(fp0, twopi2);
        !          1523:                 fp1 = floatx80_sub(fp1, fp0);
        !          1524:                 fp1 = floatx80_add(fp1, twopi2);
        !          1525:             }
        !          1526:         loop:
        !          1527:             xSign = extractFloatx80Sign(fp0);
        !          1528:             xExp = extractFloatx80Exp(fp0);
        !          1529:             xExp -= 0x3FFF;
        !          1530:             if (xExp <= 28) {
        !          1531:                 l = 0;
        !          1532:                 endflag = 1;
        !          1533:             } else {
        !          1534:                 l = xExp - 27;
        !          1535:                 endflag = 0;
        !          1536:             }
        !          1537:             invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI
        !          1538:             twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000));
        !          1539:             twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000));
        !          1540:             
        !          1541:             twoto63 = 0x5F000000;
        !          1542:             twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL
        !          1543:             
        !          1544:             fp2 = floatx80_mul(fp0, invtwopi);
        !          1545:             fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63)); // THE FRACTIONAL PART OF FP2 IS ROUNDED
        !          1546:             fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63)); // FP2 is N
        !          1547:             fp4 = floatx80_mul(twopi1, fp2); // W = N*P1
        !          1548:             fp5 = floatx80_mul(twopi2, fp2); // w = N*P2
        !          1549:             fp3 = floatx80_add(fp4, fp5); // FP3 is P
        !          1550:             fp4 = floatx80_sub(fp4, fp3); // W-P
        !          1551:             fp0 = floatx80_sub(fp0, fp3); // FP0 is A := R - P
        !          1552:             fp4 = floatx80_add(fp4, fp5); // FP4 is p = (W-P)+w
        !          1553:             fp3 = fp0; // FP3 is A
        !          1554:             fp1 = floatx80_sub(fp1, fp4); // FP1 is a := r - p
        !          1555:             fp0 = floatx80_add(fp0, fp1); // FP0 is R := A+a
        !          1556:             
        !          1557:             if (endflag > 0) {
        !          1558:                 n = floatx80_to_int32(fp2);
        !          1559:                 goto sincont;
        !          1560:             }
        !          1561:             fp3 = floatx80_sub(fp3, fp0); // A-R
        !          1562:             fp1 = floatx80_add(fp1, fp3); // FP1 is r := (A-R)+a
        !          1563:             goto loop;
        !          1564:         } else {
        !          1565:             // SINSM
        !          1566:             fp0 = float32_to_floatx80(0x3F800000); // 1
        !          1567:             
        !          1568:             float_rounding_mode = user_rnd_mode;
        !          1569:             floatx80_rounding_precision = user_rnd_prec;
        !          1570:             
        !          1571:             if (adjn) {
        !          1572:                 // COSTINY
        !          1573:                 a = floatx80_sub(fp0, float32_to_floatx80(0x00800000));
        !          1574:             } else {
        !          1575:                 // SINTINY
        !          1576:                 a = floatx80_move(a);
        !          1577:             }
        !          1578:             float_raise(float_flag_inexact);
        !          1579:             
        !          1580:             return a;
        !          1581:         }
        !          1582:     } else {
        !          1583:         fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883))); // X*2/PI
        !          1584:         
        !          1585:         n = floatx80_to_int32(fp1);
        !          1586:         j = 32 + n;
        !          1587:         
        !          1588:         fp0 = floatx80_sub(fp0, pi_tbl[j]); // X-Y1
        !          1589:         fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j])); // FP0 IS R = (X-Y1)-Y2
        !          1590:         
        !          1591:     sincont:
        !          1592:         if ((n + adjn) & 1) {
        !          1593:             // COSPOLY
        !          1594:             fp0 = floatx80_mul(fp0, fp0); // FP0 IS S
        !          1595:             fp1 = floatx80_mul(fp0, fp0); // FP1 IS T
        !          1596:             fp2 = float64_to_floatx80(LIT64(0x3D2AC4D0D6011EE3)); // B8
        !          1597:             fp3 = float64_to_floatx80(LIT64(0xBDA9396F9F45AC19)); // B7
        !          1598:             
        !          1599:             xSign = extractFloatx80Sign(fp0); // X IS S
        !          1600:             xExp = extractFloatx80Exp(fp0);
        !          1601:             xSig = extractFloatx80Frac(fp0);
        !          1602:             
        !          1603:             if (((n + adjn) >> 1) & 1) {
        !          1604:                 xSign ^= 1;
        !          1605:                 posneg1 = 0xBF800000; // -1
        !          1606:             } else {
        !          1607:                 xSign ^= 0;
        !          1608:                 posneg1 = 0x3F800000; // 1
        !          1609:             } // X IS NOW R'= SGN*R
        !          1610:             
        !          1611:             fp2 = floatx80_mul(fp2, fp1); // TB8
        !          1612:             fp3 = floatx80_mul(fp3, fp1); // TB7
        !          1613:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3E21EED90612C972))); // B6+TB8
        !          1614:             fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE927E4FB79D9FCF))); // B5+TB7
        !          1615:             fp2 = floatx80_mul(fp2, fp1); // T(B6+TB8)
        !          1616:             fp3 = floatx80_mul(fp3, fp1); // T(B5+TB7)
        !          1617:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EFA01A01A01D423))); // B4+T(B6+TB8)
        !          1618:             fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438));
        !          1619:             fp3 = floatx80_add(fp3, fp4); // B3+T(B5+TB7)
        !          1620:             fp2 = floatx80_mul(fp2, fp1); // T(B4+T(B6+TB8))
        !          1621:             fp1 = floatx80_mul(fp1, fp3); // T(B3+T(B5+TB7))
        !          1622:             fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E));
        !          1623:             fp2 = floatx80_add(fp2, fp4); // B2+T(B4+T(B6+TB8))
        !          1624:             fp1 = floatx80_add(fp1, float32_to_floatx80(0xBF000000)); // B1+T(B3+T(B5+TB7))
        !          1625:             fp0 = floatx80_mul(fp0, fp2); // S(B2+T(B4+T(B6+TB8)))
        !          1626:             fp0 = floatx80_add(fp0, fp1); // [B1+T(B3+T(B5+TB7))]+[S(B2+T(B4+T(B6+TB8)))]
        !          1627:             
        !          1628:             x = packFloatx80(xSign, xExp, xSig);
        !          1629:             fp0 = floatx80_mul(fp0, x);
        !          1630:             
        !          1631:             float_rounding_mode = user_rnd_mode;
        !          1632:             floatx80_rounding_precision = user_rnd_prec;
        !          1633:             
        !          1634:             a = floatx80_add(fp0, float32_to_floatx80(posneg1));
        !          1635:             
        !          1636:             float_raise(float_flag_inexact);
        !          1637:             
        !          1638:             return a;
        !          1639:         } else {
        !          1640:             // SINPOLY
        !          1641:             xSign = extractFloatx80Sign(fp0); // X IS R
        !          1642:             xExp = extractFloatx80Exp(fp0);
        !          1643:             xSig = extractFloatx80Frac(fp0);
        !          1644:             
        !          1645:             xSign ^= ((n + adjn) >> 1) & 1; // X IS NOW R'= SGN*R
        !          1646:             
        !          1647:             fp0 = floatx80_mul(fp0, fp0); // FP0 IS S
        !          1648:             fp1 = floatx80_mul(fp0, fp0); // FP1 IS T
        !          1649:             fp3 = float64_to_floatx80(LIT64(0xBD6AAA77CCC994F5)); // A7
        !          1650:             fp2 = float64_to_floatx80(LIT64(0x3DE612097AAE8DA1)); // A6
        !          1651:             fp3 = floatx80_mul(fp3, fp1); // T*A7
        !          1652:             fp2 = floatx80_mul(fp2, fp1); // T*A6
        !          1653:             fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBE5AE6452A118AE4))); // A5+T*A7
        !          1654:             fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3EC71DE3A5341531))); // A4+T*A6
        !          1655:             fp3 = floatx80_mul(fp3, fp1); // T(A5+TA7)
        !          1656:             fp2 = floatx80_mul(fp2, fp1); // T(A4+TA6)
        !          1657:             fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF2A01A01A018B59))); // A3+T(A5+TA7)
        !          1658:             fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF));
        !          1659:             fp2 = floatx80_add(fp2, fp4); // A2+T(A4+TA6)
        !          1660:             fp1 = floatx80_mul(fp1, fp3); // T(A3+T(A5+TA7))
        !          1661:             fp2 = floatx80_mul(fp2, fp0); // S(A2+T(A4+TA6))
        !          1662:             fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99));
        !          1663:             fp1 = floatx80_add(fp1, fp4); // A1+T(A3+T(A5+TA7))
        !          1664:             fp1 = floatx80_add(fp1, fp2); // [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))]
        !          1665:             
        !          1666:             x = packFloatx80(xSign, xExp, xSig);
        !          1667:             fp0 = floatx80_mul(fp0, x); // R'*S
        !          1668:             fp0 = floatx80_mul(fp0, fp1); // SIN(R')-R'
        !          1669:             
        !          1670:             float_rounding_mode = user_rnd_mode;
        !          1671:             floatx80_rounding_precision = user_rnd_prec;
        !          1672:             
        !          1673:             a = floatx80_add(fp0, x);
        !          1674:             
        !          1675:             float_raise(float_flag_inexact);
        !          1676:             
        !          1677:             return a;
        !          1678:         }
        !          1679:     }
        !          1680: }
        !          1681: 
        !          1682: /*----------------------------------------------------------------------------
        !          1683:  | Hyperbolic sine
        !          1684:  *----------------------------------------------------------------------------*/
        !          1685: 
        !          1686: floatx80 floatx80_sinh(floatx80 a)
        !          1687: {
        !          1688:     flag aSign;
        !          1689:     int32 aExp;
        !          1690:     bits64 aSig;
        !          1691:     
        !          1692:     int8 user_rnd_mode, user_rnd_prec;
        !          1693:     
        !          1694:     int32 compact;
        !          1695:     floatx80 fp0, fp1, fp2;
        !          1696:     float32 fact;
        !          1697:     
        !          1698:     aSig = extractFloatx80Frac(a);
        !          1699:     aExp = extractFloatx80Exp(a);
        !          1700:     aSign = extractFloatx80Sign(a);
        !          1701:     
        !          1702:     if (aExp == 0x7FFF) {
        !          1703:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a);
        !          1704:         return packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low);
        !          1705:     }
        !          1706:     
        !          1707:     if (aExp == 0 && aSig == 0) {
        !          1708:         return packFloatx80(aSign, 0, 0);
        !          1709:     }
        !          1710:     
        !          1711:     user_rnd_mode = float_rounding_mode;
        !          1712:     user_rnd_prec = floatx80_rounding_precision;
        !          1713:     float_rounding_mode = float_round_nearest_even;
        !          1714:     floatx80_rounding_precision = 80;
        !          1715:     
        !          1716:     compact = floatx80_make_compact(aExp, aSig);
        !          1717: 
        !          1718:     if (compact > 0x400CB167) {
        !          1719:         // SINHBIG
        !          1720:         if (compact > 0x400CB2B3) {
        !          1721:             float_rounding_mode = user_rnd_mode;
        !          1722:             floatx80_rounding_precision = user_rnd_prec;
        !          1723:             
        !          1724:             return roundAndPackFloatx80(floatx80_rounding_precision, aSign, 0x8000, aSig, 0);
        !          1725:         } else {
        !          1726:             fp0 = floatx80_abs(a); // Y = |X|
        !          1727:             fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x40C62D38D3D64634))); // (|X|-16381LOG2_LEAD)
        !          1728:             fp0 = floatx80_sub(fp0, float64_to_floatx80(LIT64(0x3D6F90AEB1E75CC7))); // |X| - 16381 LOG2, ACCURATE
        !          1729:             fp0 = floatx80_etox(fp0);
        !          1730:             fp2 = packFloatx80(aSign, 0x7FFB, one_sig);
        !          1731:             
        !          1732:             float_rounding_mode = user_rnd_mode;
        !          1733:             floatx80_rounding_precision = user_rnd_prec;
        !          1734:             
        !          1735:             a = floatx80_mul(fp0, fp2);
        !          1736:             
        !          1737:             float_raise(float_flag_inexact);
        !          1738:             
        !          1739:             return a;
        !          1740:         }
        !          1741:     } else { // |X| < 16380 LOG2
        !          1742:         fp0 = floatx80_abs(a); // Y = |X|
        !          1743:         fp0 = floatx80_etoxm1(fp0); // FP0 IS Z = EXPM1(Y)
        !          1744:         fp1 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // 1+Z
        !          1745:         fp2 = fp0;
        !          1746:         fp0 = floatx80_div(fp0, fp1); // Z/(1+Z)
        !          1747:         fp0 = floatx80_add(fp0, fp2);
        !          1748:         
        !          1749:         fact = 0x3F000000;
        !          1750:         fact |= aSign ? 0x80000000 : 0x00000000;
        !          1751:         
        !          1752:         float_rounding_mode = user_rnd_mode;
        !          1753:         floatx80_rounding_precision = user_rnd_prec;
        !          1754:         
        !          1755:         a = floatx80_mul(fp0, float32_to_floatx80(fact));
        !          1756:         
        !          1757:         float_raise(float_flag_inexact);
        !          1758:         
        !          1759:         return a;
        !          1760:     }
        !          1761: }
        !          1762: 
        !          1763: /*----------------------------------------------------------------------------
        !          1764:  | Tangent
        !          1765:  *----------------------------------------------------------------------------*/
        !          1766: 
        !          1767: floatx80 floatx80_tan(floatx80 a)
        !          1768: {
        !          1769:     flag aSign, xSign;
        !          1770:     int32 aExp, xExp;
        !          1771:     bits64 aSig, xSig;
        !          1772:     
        !          1773:     int8 user_rnd_mode, user_rnd_prec;
        !          1774:     
        !          1775:     int32 compact, l, n, j;
        !          1776:     floatx80 fp0, fp1, fp2, fp3, fp4, fp5, invtwopi, twopi1, twopi2;
        !          1777:     float32 twoto63;
        !          1778:     flag endflag;
        !          1779:     
        !          1780:     aSig = extractFloatx80Frac(a);
        !          1781:     aExp = extractFloatx80Exp(a);
        !          1782:     aSign = extractFloatx80Sign(a);
        !          1783:     
        !          1784:     if (aExp == 0x7FFF) {
        !          1785:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a);
        !          1786:         float_raise(float_flag_invalid);
        !          1787:         a.low = floatx80_default_nan_low;
        !          1788:         a.high = floatx80_default_nan_high;
        !          1789:         return a;
        !          1790:     }
        !          1791:     
        !          1792:     if (aExp == 0 && aSig == 0) {
        !          1793:         return packFloatx80(aSign, 0, 0);
        !          1794:     }
        !          1795:     
        !          1796:     user_rnd_mode = float_rounding_mode;
        !          1797:     user_rnd_prec = floatx80_rounding_precision;
        !          1798:     float_rounding_mode = float_round_nearest_even;
        !          1799:     floatx80_rounding_precision = 80;
        !          1800:     
        !          1801:     compact = floatx80_make_compact(aExp, aSig);
        !          1802:     
        !          1803:     fp0 = a;
        !          1804:     
        !          1805:     if (compact < 0x3FD78000 || compact > 0x4004BC7E) { // 2^(-40) > |X| > 15 PI
        !          1806:         if (compact > 0x3FFF8000) { // |X| >= 15 PI
        !          1807:             // REDUCEX
        !          1808:             fp1 = packFloatx80(0, 0, 0);
        !          1809:             if (compact == 0x7FFEFFFF) {
        !          1810:                 twopi1 = packFloatx80(aSign ^ 1, 0x7FFE, LIT64(0xC90FDAA200000000));
        !          1811:                 twopi2 = packFloatx80(aSign ^ 1, 0x7FDC, LIT64(0x85A308D300000000));
        !          1812:                 fp0 = floatx80_add(fp0, twopi1);
        !          1813:                 fp1 = fp0;
        !          1814:                 fp0 = floatx80_add(fp0, twopi2);
        !          1815:                 fp1 = floatx80_sub(fp1, fp0);
        !          1816:                 fp1 = floatx80_add(fp1, twopi2);
        !          1817:             }
        !          1818:         loop:
        !          1819:             xSign = extractFloatx80Sign(fp0);
        !          1820:             xExp = extractFloatx80Exp(fp0);
        !          1821:             xExp -= 0x3FFF;
        !          1822:             if (xExp <= 28) {
        !          1823:                 l = 0;
        !          1824:                 endflag = 1;
        !          1825:             } else {
        !          1826:                 l = xExp - 27;
        !          1827:                 endflag = 0;
        !          1828:             }
        !          1829:             invtwopi = packFloatx80(0, 0x3FFE - l, LIT64(0xA2F9836E4E44152A)); // INVTWOPI
        !          1830:             twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000));
        !          1831:             twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000));
        !          1832:             
        !          1833:             twoto63 = 0x5F000000;
        !          1834:             twoto63 |= xSign ? 0x80000000 : 0x00000000; // SIGN(INARG)*2^63 IN SGL
        !          1835:             
        !          1836:             fp2 = floatx80_mul(fp0, invtwopi);
        !          1837:             fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63)); // THE FRACTIONAL PART OF FP2 IS ROUNDED
        !          1838:             fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63)); // FP2 is N
        !          1839:             fp4 = floatx80_mul(twopi1, fp2); // W = N*P1
        !          1840:             fp5 = floatx80_mul(twopi2, fp2); // w = N*P2
        !          1841:             fp3 = floatx80_add(fp4, fp5); // FP3 is P
        !          1842:             fp4 = floatx80_sub(fp4, fp3); // W-P
        !          1843:             fp0 = floatx80_sub(fp0, fp3); // FP0 is A := R - P
        !          1844:             fp4 = floatx80_add(fp4, fp5); // FP4 is p = (W-P)+w
        !          1845:             fp3 = fp0; // FP3 is A
        !          1846:             fp1 = floatx80_sub(fp1, fp4); // FP1 is a := r - p
        !          1847:             fp0 = floatx80_add(fp0, fp1); // FP0 is R := A+a
        !          1848:             
        !          1849:             if (endflag > 0) {
        !          1850:                 n = floatx80_to_int32(fp2);
        !          1851:                 goto tancont;
        !          1852:             }
        !          1853:             fp3 = floatx80_sub(fp3, fp0); // A-R
        !          1854:             fp1 = floatx80_add(fp1, fp3); // FP1 is r := (A-R)+a
        !          1855:             goto loop;
        !          1856:         } else {
        !          1857:             float_rounding_mode = user_rnd_mode;
        !          1858:             floatx80_rounding_precision = user_rnd_prec;
        !          1859:             
        !          1860:             a = floatx80_move(a);
        !          1861:             
        !          1862:             float_raise(float_flag_inexact);
        !          1863:             
        !          1864:             return a;
        !          1865:         }
        !          1866:     } else {
        !          1867:         fp1 = floatx80_mul(fp0, float64_to_floatx80(LIT64(0x3FE45F306DC9C883))); // X*2/PI
        !          1868:         
        !          1869:         n = floatx80_to_int32(fp1);
        !          1870:         j = 32 + n;
        !          1871:         
        !          1872:         fp0 = floatx80_sub(fp0, pi_tbl[j]); // X-Y1
        !          1873:         fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j])); // FP0 IS R = (X-Y1)-Y2
        !          1874:         
        !          1875:     tancont:
        !          1876:         if (n & 1) {
        !          1877:             // NODD
        !          1878:             fp1 = fp0; // R
        !          1879:             fp0 = floatx80_mul(fp0, fp0); // S = R*R
        !          1880:             fp3 = float64_to_floatx80(LIT64(0x3EA0B759F50F8688)); // Q4
        !          1881:             fp2 = float64_to_floatx80(LIT64(0xBEF2BAA5A8924F04)); // P3
        !          1882:             fp3 = floatx80_mul(fp3, fp0); // SQ4
        !          1883:             fp2 = floatx80_mul(fp2, fp0); // SP3
        !          1884:             fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF346F59B39BA65F))); // Q3+SQ4
        !          1885:             fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00));
        !          1886:             fp2 = floatx80_add(fp2, fp4); // P2+SP3
        !          1887:             fp3 = floatx80_mul(fp3, fp0); // S(Q3+SQ4)
        !          1888:             fp2 = floatx80_mul(fp2, fp0); // S(P2+SP3)
        !          1889:             fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1));
        !          1890:             fp3 = floatx80_add(fp3, fp4); // Q2+S(Q3+SQ4)
        !          1891:             fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA));
        !          1892:             fp2 = floatx80_add(fp2, fp4); // P1+S(P2+SP3)
        !          1893:             fp3 = floatx80_mul(fp3, fp0); // S(Q2+S(Q3+SQ4))
        !          1894:             fp2 = floatx80_mul(fp2, fp0); // S(P1+S(P2+SP3))
        !          1895:             fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE));
        !          1896:             fp3 = floatx80_add(fp3, fp4); // Q1+S(Q2+S(Q3+SQ4))
        !          1897:             fp2 = floatx80_mul(fp2, fp1); // RS(P1+S(P2+SP3))
        !          1898:             fp0 = floatx80_mul(fp0, fp3); // S(Q1+S(Q2+S(Q3+SQ4)))
        !          1899:             fp1 = floatx80_add(fp1, fp2); // R+RS(P1+S(P2+SP3))
        !          1900:             fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // 1+S(Q1+S(Q2+S(Q3+SQ4)))
        !          1901:             
        !          1902:             xSign = extractFloatx80Sign(fp1);
        !          1903:             xExp = extractFloatx80Exp(fp1);
        !          1904:             xSig = extractFloatx80Frac(fp1);
        !          1905:             xSign ^= 1;
        !          1906:             fp1 = packFloatx80(xSign, xExp, xSig);
        !          1907: 
        !          1908:             float_rounding_mode = user_rnd_mode;
        !          1909:             floatx80_rounding_precision = user_rnd_prec;
        !          1910:             
        !          1911:             a = floatx80_div(fp0, fp1);
        !          1912:             
        !          1913:             float_raise(float_flag_inexact);
        !          1914:             
        !          1915:             return a;
        !          1916:         } else {
        !          1917:             fp1 = floatx80_mul(fp0, fp0); // S = R*R
        !          1918:             fp3 = float64_to_floatx80(LIT64(0x3EA0B759F50F8688)); // Q4
        !          1919:             fp2 = float64_to_floatx80(LIT64(0xBEF2BAA5A8924F04)); // P3
        !          1920:             fp3 = floatx80_mul(fp3, fp1); // SQ4
        !          1921:             fp2 = floatx80_mul(fp2, fp1); // SP3
        !          1922:             fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0xBF346F59B39BA65F))); // Q3+SQ4
        !          1923:             fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00));
        !          1924:             fp2 = floatx80_add(fp2, fp4); // P2+SP3
        !          1925:             fp3 = floatx80_mul(fp3, fp1); // S(Q3+SQ4)
        !          1926:             fp2 = floatx80_mul(fp2, fp1); // S(P2+SP3)
        !          1927:             fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1));
        !          1928:             fp3 = floatx80_add(fp3, fp4); // Q2+S(Q3+SQ4)
        !          1929:             fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA));
        !          1930:             fp2 = floatx80_add(fp2, fp4); // P1+S(P2+SP3)
        !          1931:             fp3 = floatx80_mul(fp3, fp1); // S(Q2+S(Q3+SQ4))
        !          1932:             fp2 = floatx80_mul(fp2, fp1); // S(P1+S(P2+SP3))
        !          1933:             fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE));
        !          1934:             fp3 = floatx80_add(fp3, fp4); // Q1+S(Q2+S(Q3+SQ4))
        !          1935:             fp2 = floatx80_mul(fp2, fp0); // RS(P1+S(P2+SP3))
        !          1936:             fp1 = floatx80_mul(fp1, fp3); // S(Q1+S(Q2+S(Q3+SQ4)))
        !          1937:             fp0 = floatx80_add(fp0, fp2); // R+RS(P1+S(P2+SP3))
        !          1938:             fp1 = floatx80_add(fp1, float32_to_floatx80(0x3F800000)); // 1+S(Q1+S(Q2+S(Q3+SQ4)))
        !          1939:             
        !          1940:             float_rounding_mode = user_rnd_mode;
        !          1941:             floatx80_rounding_precision = user_rnd_prec;
        !          1942:             
        !          1943:             a = floatx80_div(fp0, fp1);
        !          1944:             
        !          1945:             float_raise(float_flag_inexact);
        !          1946:             
        !          1947:             return a;
        !          1948:         }
        !          1949:     }
        !          1950: }
        !          1951: 
        !          1952: /*----------------------------------------------------------------------------
        !          1953:  | Hyperbolic tangent
        !          1954:  *----------------------------------------------------------------------------*/
        !          1955: 
        !          1956: floatx80 floatx80_tanh(floatx80 a)
        !          1957: {
        !          1958:     flag aSign, vSign;
        !          1959:     int32 aExp, vExp;
        !          1960:     bits64 aSig, vSig;
        !          1961:     
        !          1962:     int8 user_rnd_mode, user_rnd_prec;
        !          1963:     
        !          1964:     int32 compact;
        !          1965:     floatx80 fp0, fp1;
        !          1966:     float32 sign;
        !          1967:     
        !          1968:     aSig = extractFloatx80Frac(a);
        !          1969:     aExp = extractFloatx80Exp(a);
        !          1970:     aSign = extractFloatx80Sign(a);
        !          1971:     
        !          1972:     if (aExp == 0x7FFF) {
        !          1973:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a);
        !          1974:         return packFloatx80(aSign, one_exp, one_sig);
        !          1975:     }
        !          1976:     
        !          1977:     if (aExp == 0 && aSig == 0) {
        !          1978:         return packFloatx80(aSign, 0, 0);
        !          1979:     }
        !          1980:     
        !          1981:     user_rnd_mode = float_rounding_mode;
        !          1982:     user_rnd_prec = floatx80_rounding_precision;
        !          1983:     float_rounding_mode = float_round_nearest_even;
        !          1984:     floatx80_rounding_precision = 80;
        !          1985:     
        !          1986:     compact = floatx80_make_compact(aExp, aSig);
        !          1987:     
        !          1988:     if (compact < 0x3FD78000 || compact > 0x3FFFDDCE) {
        !          1989:         // TANHBORS
        !          1990:         if (compact < 0x3FFF8000) {
        !          1991:             // TANHSM
        !          1992:             float_rounding_mode = user_rnd_mode;
        !          1993:             floatx80_rounding_precision = user_rnd_prec;
        !          1994:             
        !          1995:             a = floatx80_move(a);
        !          1996:             
        !          1997:             float_raise(float_flag_inexact);
        !          1998:             
        !          1999:             return a;
        !          2000:         } else {
        !          2001:             if (compact > 0x40048AA1) {
        !          2002:                 // TANHHUGE
        !          2003:                 sign = 0x3F800000;
        !          2004:                 sign |= aSign ? 0x80000000 : 0x00000000;
        !          2005:                 fp0 = float32_to_floatx80(sign);
        !          2006:                 sign &= 0x80000000;
        !          2007:                 sign ^= 0x80800000; // -SIGN(X)*EPS
        !          2008:                 
        !          2009:                 float_rounding_mode = user_rnd_mode;
        !          2010:                 floatx80_rounding_precision = user_rnd_prec;
        !          2011:                 
        !          2012:                 a = floatx80_add(fp0, float32_to_floatx80(sign));
        !          2013:                 
        !          2014:                 float_raise(float_flag_inexact);
        !          2015:                 
        !          2016:                 return a;
        !          2017:             } else {
        !          2018:                 fp0 = packFloatx80(0, aExp+1, aSig); // Y = 2|X|
        !          2019:                 fp0 = floatx80_etox(fp0); // FP0 IS EXP(Y)
        !          2020:                 fp0 = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // EXP(Y)+1
        !          2021:                 sign = aSign ? 0x80000000 : 0x00000000;
        !          2022:                 fp1 = floatx80_div(float32_to_floatx80(sign^0xC0000000), fp0); // -SIGN(X)*2 / [EXP(Y)+1]
        !          2023:                 fp0 = float32_to_floatx80(sign | 0x3F800000); // SIGN
        !          2024:                 
        !          2025:                 float_rounding_mode = user_rnd_mode;
        !          2026:                 floatx80_rounding_precision = user_rnd_prec;
        !          2027:                 
        !          2028:                 a = floatx80_add(fp1, fp0);
        !          2029:                 
        !          2030:                 float_raise(float_flag_inexact);
        !          2031:                 
        !          2032:                 return a;
        !          2033:             }
        !          2034:         }
        !          2035:     } else { // 2**(-40) < |X| < (5/2)LOG2
        !          2036:         fp0 = packFloatx80(0, aExp+1, aSig); // Y = 2|X|
        !          2037:         fp0 = floatx80_etoxm1(fp0); // FP0 IS Z = EXPM1(Y)
        !          2038:         fp1 = floatx80_add(fp0, float32_to_floatx80(0x40000000)); // Z+2
        !          2039:         
        !          2040:         vSign = extractFloatx80Sign(fp1);
        !          2041:         vExp = extractFloatx80Exp(fp1);
        !          2042:         vSig = extractFloatx80Frac(fp1);
        !          2043:         
        !          2044:         fp1 = packFloatx80(vSign ^ aSign, vExp, vSig);
        !          2045:         
        !          2046:         float_rounding_mode = user_rnd_mode;
        !          2047:         floatx80_rounding_precision = user_rnd_prec;
        !          2048:         
        !          2049:         a = floatx80_div(fp0, fp1);
        !          2050:         
        !          2051:         float_raise(float_flag_inexact);
        !          2052:         
        !          2053:         return a;
        !          2054:     }
        !          2055: }
        !          2056: 
        !          2057: /*----------------------------------------------------------------------------
        !          2058:  | 10 to x
        !          2059:  *----------------------------------------------------------------------------*/
        !          2060: 
        !          2061: floatx80 floatx80_tentox(floatx80 a)
        !          2062: {
        !          2063:     flag aSign;
        !          2064:     int32 aExp;
        !          2065:     bits64 aSig;
        !          2066:     
        !          2067:     int8 user_rnd_mode, user_rnd_prec;
        !          2068:     
        !          2069:     int32 compact, n, j, l, m, m1;
        !          2070:     floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2;
        !          2071:     
        !          2072:     aSig = extractFloatx80Frac(a);
        !          2073:     aExp = extractFloatx80Exp(a);
        !          2074:     aSign = extractFloatx80Sign(a);
        !          2075:     
        !          2076:     if (aExp == 0x7FFF) {
        !          2077:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a);
        !          2078:         if (aSign) return packFloatx80(0, 0, 0);
        !          2079:         return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low);
        !          2080:     }
        !          2081:     
        !          2082:     if (aExp == 0 && aSig == 0) {
        !          2083:         return packFloatx80(0, one_exp, one_sig);
        !          2084:     }
        !          2085:     
        !          2086:     user_rnd_mode = float_rounding_mode;
        !          2087:     user_rnd_prec = floatx80_rounding_precision;
        !          2088:     float_rounding_mode = float_round_nearest_even;
        !          2089:     floatx80_rounding_precision = 80;
        !          2090:     
        !          2091:     fp0 = a;
        !          2092:     
        !          2093:     compact = floatx80_make_compact(aExp, aSig);
        !          2094:     
        !          2095:     if (compact < 0x3FB98000 || compact > 0x400B9B07) { // |X| > 16480 LOG2/LOG10 or |X| < 2^(-70)
        !          2096:         if (compact > 0x3FFF8000) { // |X| > 16480
        !          2097:             float_rounding_mode = user_rnd_mode;
        !          2098:             floatx80_rounding_precision = user_rnd_prec;
        !          2099:             
        !          2100:             if (aSign) {
        !          2101:                 return roundAndPackFloatx80(floatx80_rounding_precision, 0, -0x1000, aSig, 0);
        !          2102:             } else {
        !          2103:                 return roundAndPackFloatx80(floatx80_rounding_precision, 0, 0x8000, aSig, 0);
        !          2104:             }
        !          2105:         } else { // |X| < 2^(-70)
        !          2106:             float_rounding_mode = user_rnd_mode;
        !          2107:             floatx80_rounding_precision = user_rnd_prec;
        !          2108:             
        !          2109:             a = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // 1 + X
        !          2110:             
        !          2111:             float_raise(float_flag_inexact);
        !          2112:             
        !          2113:             return a;
        !          2114:         }
        !          2115:     } else { // 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10
        !          2116:         fp1 = fp0; // X
        !          2117:         fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x406A934F0979A371))); // X*64*LOG10/LOG2
        !          2118:         n = floatx80_to_int32(fp1); // N=INT(X*64*LOG10/LOG2)
        !          2119:         fp1 = int32_to_floatx80(n);
        !          2120: 
        !          2121:         j = n & 0x3F;
        !          2122:         l = n / 64; // NOTE: this is really arithmetic right shift by 6
        !          2123:         if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity
        !          2124:             l--;
        !          2125:         }
        !          2126:         m = l / 2; // NOTE: this is really arithmetic right shift by 1
        !          2127:         if (l < 0 && (l & 1)) { // arithmetic right shift is division and round towards minus infinity
        !          2128:             m--;
        !          2129:         }
        !          2130:         m1 = l - m;
        !          2131:         m1 += 0x3FFF; // ADJFACT IS 2^(M')
        !          2132: 
        !          2133:         adjfact = packFloatx80(0, m1, one_sig);
        !          2134:         fact1 = exp2_tbl[j];
        !          2135:         fact1.high += m;
        !          2136:         fact2.high = exp2_tbl2[j]>>16;
        !          2137:         fact2.high += m;
        !          2138:         fact2.low = (bits64)(exp2_tbl2[j] & 0xFFFF);
        !          2139:         fact2.low <<= 48;
        !          2140:         
        !          2141:         fp2 = fp1; // N
        !          2142:         fp1 = floatx80_mul(fp1, float64_to_floatx80(LIT64(0x3F734413509F8000))); // N*(LOG2/64LOG10)_LEAD
        !          2143:         fp3 = packFloatx80(1, 0x3FCD, LIT64(0xC0219DC1DA994FD2));
        !          2144:         fp2 = floatx80_mul(fp2, fp3); // N*(LOG2/64LOG10)_TRAIL
        !          2145:         fp0 = floatx80_sub(fp0, fp1); // X - N L_LEAD
        !          2146:         fp0 = floatx80_sub(fp0, fp2); // X - N L_TRAIL
        !          2147:         fp2 = packFloatx80(0, 0x4000, LIT64(0x935D8DDDAAA8AC17)); // LOG10
        !          2148:         fp0 = floatx80_mul(fp0, fp2); // R
        !          2149:         
        !          2150:         // EXPR
        !          2151:         fp1 = floatx80_mul(fp0, fp0); // S = R*R
        !          2152:         fp2 = float64_to_floatx80(LIT64(0x3F56C16D6F7BD0B2)); // A5
        !          2153:         fp3 = float64_to_floatx80(LIT64(0x3F811112302C712C)); // A4
        !          2154:         fp2 = floatx80_mul(fp2, fp1); // S*A5
        !          2155:         fp3 = floatx80_mul(fp3, fp1); // S*A4
        !          2156:         fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554CC1))); // A3+S*A5
        !          2157:         fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554A54))); // A2+S*A4
        !          2158:         fp2 = floatx80_mul(fp2, fp1); // S*(A3+S*A5)
        !          2159:         fp3 = floatx80_mul(fp3, fp1); // S*(A2+S*A4)
        !          2160:         fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FE0000000000000))); // A1+S*(A3+S*A5)
        !          2161:         fp3 = floatx80_mul(fp3, fp0); // R*S*(A2+S*A4)
        !          2162:         
        !          2163:         fp2 = floatx80_mul(fp2, fp1); // S*(A1+S*(A3+S*A5))
        !          2164:         fp0 = floatx80_add(fp0, fp3); // R+R*S*(A2+S*A4)
        !          2165:         fp0 = floatx80_add(fp0, fp2); // EXP(R) - 1
        !          2166:         
        !          2167:         fp0 = floatx80_mul(fp0, fact1);
        !          2168:         fp0 = floatx80_add(fp0, fact2);
        !          2169:         fp0 = floatx80_add(fp0, fact1);
        !          2170:         
        !          2171:         float_rounding_mode = user_rnd_mode;
        !          2172:         floatx80_rounding_precision = user_rnd_prec;
        !          2173:         
        !          2174:         a = floatx80_mul(fp0, adjfact);
        !          2175:         
        !          2176:         float_raise(float_flag_inexact);
        !          2177:         
        !          2178:         return a;
        !          2179:     }
        !          2180: }
        !          2181: 
        !          2182: /*----------------------------------------------------------------------------
        !          2183:  | 2 to x
        !          2184:  *----------------------------------------------------------------------------*/
        !          2185: 
        !          2186: floatx80 floatx80_twotox(floatx80 a)
        !          2187: {
        !          2188:     flag aSign;
        !          2189:     int32 aExp;
        !          2190:     bits64 aSig;
        !          2191:     
        !          2192:     int8 user_rnd_mode, user_rnd_prec;
        !          2193:     
        !          2194:     int32 compact, n, j, l, m, m1;
        !          2195:     floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2;
        !          2196:     
        !          2197:     aSig = extractFloatx80Frac(a);
        !          2198:     aExp = extractFloatx80Exp(a);
        !          2199:     aSign = extractFloatx80Sign(a);
        !          2200:     
        !          2201:     if (aExp == 0x7FFF) {
        !          2202:         if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a);
        !          2203:         if (aSign) return packFloatx80(0, 0, 0);
        !          2204:         return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low);
        !          2205:     }
        !          2206:     
        !          2207:     if (aExp == 0 && aSig == 0) {
        !          2208:         return packFloatx80(0, one_exp, one_sig);
        !          2209:     }
        !          2210:     
        !          2211:     user_rnd_mode = float_rounding_mode;
        !          2212:     user_rnd_prec = floatx80_rounding_precision;
        !          2213:     float_rounding_mode = float_round_nearest_even;
        !          2214:     floatx80_rounding_precision = 80;
        !          2215:     
        !          2216:     fp0 = a;
        !          2217:     
        !          2218:     compact = floatx80_make_compact(aExp, aSig);
        !          2219:     
        !          2220:     if (compact < 0x3FB98000 || compact > 0x400D80C0) { // |X| > 16480 or |X| < 2^(-70)
        !          2221:         if (compact > 0x3FFF8000) { // |X| > 16480
        !          2222:             float_rounding_mode = user_rnd_mode;
        !          2223:             floatx80_rounding_precision = user_rnd_prec;
        !          2224:             
        !          2225:             if (aSign) {
        !          2226:                 return roundAndPackFloatx80(floatx80_rounding_precision, 0, -0x1000, aSig, 0);
        !          2227:             } else {
        !          2228:                 return roundAndPackFloatx80(floatx80_rounding_precision, 0, 0x8000, aSig, 0);
        !          2229:             }
        !          2230:         } else { // |X| < 2^(-70)
        !          2231:             float_rounding_mode = user_rnd_mode;
        !          2232:             floatx80_rounding_precision = user_rnd_prec;
        !          2233:             
        !          2234:             a = floatx80_add(fp0, float32_to_floatx80(0x3F800000)); // 1 + X
        !          2235:             
        !          2236:             float_raise(float_flag_inexact);
        !          2237:             
        !          2238:             return a;
        !          2239:         }
        !          2240:     } else { // 2^(-70) <= |X| <= 16480
        !          2241:         fp1 = fp0; // X
        !          2242:         fp1 = floatx80_mul(fp1, float32_to_floatx80(0x42800000)); // X * 64
        !          2243:         n = floatx80_to_int32(fp1);
        !          2244:         fp1 = int32_to_floatx80(n);
        !          2245:         j = n & 0x3F;
        !          2246:         l = n / 64; // NOTE: this is really arithmetic right shift by 6
        !          2247:         if (n < 0 && j) { // arithmetic right shift is division and round towards minus infinity
        !          2248:             l--;
        !          2249:         }
        !          2250:         m = l / 2; // NOTE: this is really arithmetic right shift by 1
        !          2251:         if (l < 0 && (l & 1)) { // arithmetic right shift is division and round towards minus infinity
        !          2252:             m--;
        !          2253:         }
        !          2254:         m1 = l - m;
        !          2255:         m1 += 0x3FFF; // ADJFACT IS 2^(M')
        !          2256:         
        !          2257:         adjfact = packFloatx80(0, m1, one_sig);
        !          2258:         fact1 = exp2_tbl[j];
        !          2259:         fact1.high += m;
        !          2260:         fact2.high = exp2_tbl2[j]>>16;
        !          2261:         fact2.high += m;
        !          2262:         fact2.low = (bits64)(exp2_tbl2[j] & 0xFFFF);
        !          2263:         fact2.low <<= 48;
        !          2264:         
        !          2265:         fp1 = floatx80_mul(fp1, float32_to_floatx80(0x3C800000)); // (1/64)*N
        !          2266:         fp0 = floatx80_sub(fp0, fp1); // X - (1/64)*INT(64 X)
        !          2267:         fp2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); // LOG2
        !          2268:         fp0 = floatx80_mul(fp0, fp2); // R
        !          2269:         
        !          2270:         // EXPR
        !          2271:         fp1 = floatx80_mul(fp0, fp0); // S = R*R
        !          2272:         fp2 = float64_to_floatx80(LIT64(0x3F56C16D6F7BD0B2)); // A5
        !          2273:         fp3 = float64_to_floatx80(LIT64(0x3F811112302C712C)); // A4
        !          2274:         fp2 = floatx80_mul(fp2, fp1); // S*A5
        !          2275:         fp3 = floatx80_mul(fp3, fp1); // S*A4
        !          2276:         fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FA5555555554CC1))); // A3+S*A5
        !          2277:         fp3 = floatx80_add(fp3, float64_to_floatx80(LIT64(0x3FC5555555554A54))); // A2+S*A4
        !          2278:         fp2 = floatx80_mul(fp2, fp1); // S*(A3+S*A5)
        !          2279:         fp3 = floatx80_mul(fp3, fp1); // S*(A2+S*A4)
        !          2280:         fp2 = floatx80_add(fp2, float64_to_floatx80(LIT64(0x3FE0000000000000))); // A1+S*(A3+S*A5)
        !          2281:         fp3 = floatx80_mul(fp3, fp0); // R*S*(A2+S*A4)
        !          2282:         
        !          2283:         fp2 = floatx80_mul(fp2, fp1); // S*(A1+S*(A3+S*A5))
        !          2284:         fp0 = floatx80_add(fp0, fp3); // R+R*S*(A2+S*A4)
        !          2285:         fp0 = floatx80_add(fp0, fp2); // EXP(R) - 1
        !          2286:         
        !          2287:         fp0 = floatx80_mul(fp0, fact1);
        !          2288:         fp0 = floatx80_add(fp0, fact2);
        !          2289:         fp0 = floatx80_add(fp0, fact1);
        !          2290:         
        !          2291:         float_rounding_mode = user_rnd_mode;
        !          2292:         floatx80_rounding_precision = user_rnd_prec;
        !          2293:         
        !          2294:         a = floatx80_mul(fp0, adjfact);
        !          2295:         
        !          2296:         float_raise(float_flag_inexact);
        !          2297:         
        !          2298:         return a;
        !          2299:     }
        !          2300: }

unix.superglobalmegacorp.com

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