📄 dtoa.cpp
字号:
#endif if (k > 0) word0(da) += k * Exp_msk1; else { k = -k; word0(db) += k * Exp_msk1; } return dval(da) / dval(db);}static const double tens[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};static const double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,#ifdef Avoid_Underflow 9007199254740992. * 9007199254740992.e-256 /* = 2^106 * 1e-53 */#else 1e-256#endif};/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow *//* flag unnecessarily. It leads to a song and dance at the end of strtod. */#define Scale_Bit 0x10#define n_bigtens 5#if defined(INFNAN_CHECK)#ifndef NAN_WORD0#define NAN_WORD0 0x7ff80000#endif#ifndef NAN_WORD1#define NAN_WORD1 0#endifstatic int match(const char** sp, const char* t){ int c, d; const char* s = *sp; while ((d = *t++)) { if ((c = *++s) >= 'A' && c <= 'Z') c += 'a' - 'A'; if (c != d) return 0; } *sp = s + 1; return 1;}#ifndef No_Hex_NaNstatic void hexnan(double* rvp, const char** sp){ uint32_t c, x[2]; const char* s; int havedig, udx0, xshift; x[0] = x[1] = 0; havedig = xshift = 0; udx0 = 1; s = *sp; while ((c = *(const unsigned char*)++s)) { if (c >= '0' && c <= '9') c -= '0'; else if (c >= 'a' && c <= 'f') c += 10 - 'a'; else if (c >= 'A' && c <= 'F') c += 10 - 'A'; else if (c <= ' ') { if (udx0 && havedig) { udx0 = 0; xshift = 1; } continue; } else if (/*(*/ c == ')' && havedig) { *sp = s + 1; break; } else return; /* invalid form: don't change *sp */ havedig = 1; if (xshift) { xshift = 0; x[0] = x[1]; x[1] = 0; } if (udx0) x[0] = (x[0] << 4) | (x[1] >> 28); x[1] = (x[1] << 4) | c; } if ((x[0] &= 0xfffff) || x[1]) { word0(*rvp) = Exp_mask | x[0]; word1(*rvp) = x[1]; }}#endif /*No_Hex_NaN*/#endif /* INFNAN_CHECK */double strtod(const char* s00, char** se){#ifdef Avoid_Underflow int scale;#endif int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; const char *s, *s0, *s1; double aadj, aadj1, adj, rv, rv0; int32_t L; uint32_t y, z; Bigint *bb = NULL, *bb1 = NULL, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL;#ifdef SET_INEXACT int inexact, oldinexact;#endif sign = nz0 = nz = 0; dval(rv) = 0.; for (s = s00; ; s++) switch (*s) { case '-': sign = 1; /* no break */ case '+': if (*++s) goto break2; /* no break */ case 0: goto ret0; case '\t': case '\n': case '\v': case '\f': case '\r': case ' ': continue; default: goto break2; }break2: if (*s == '0') { nz0 = 1; while (*++s == '0') { } if (!*s) goto ret; } s0 = s; y = z = 0; for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) if (nd < 9) y = (10 * y) + c - '0'; else if (nd < 16) z = (10 * z) + c - '0'; nd0 = nd; if (c == '.') { c = *++s; if (!nd) { for (; c == '0'; c = *++s) nz++; if (c > '0' && c <= '9') { s0 = s; nf += nz; nz = 0; goto have_dig; } goto dig_done; } for (; c >= '0' && c <= '9'; c = *++s) {have_dig: nz++; if (c -= '0') { nf += nz; for (i = 1; i < nz; i++) if (nd++ < 9) y *= 10; else if (nd <= DBL_DIG + 1) z *= 10; if (nd++ < 9) y = (10 * y) + c; else if (nd <= DBL_DIG + 1) z = (10 * z) + c; nz = 0; } } }dig_done: e = 0; if (c == 'e' || c == 'E') { if (!nd && !nz && !nz0) { goto ret0; } s00 = s; esign = 0; switch (c = *++s) { case '-': esign = 1; case '+': c = *++s; } if (c >= '0' && c <= '9') { while (c == '0') c = *++s; if (c > '0' && c <= '9') { L = c - '0'; s1 = s; while ((c = *++s) >= '0' && c <= '9') L = (10 * L) + c - '0'; if (s - s1 > 8 || L > 19999) /* Avoid confusion from exponents * so large that e might overflow. */ e = 19999; /* safe for 16 bit ints */ else e = (int)L; if (esign) e = -e; } else e = 0; } else s = s00; } if (!nd) { if (!nz && !nz0) {#ifdef INFNAN_CHECK /* Check for Nan and Infinity */ switch(c) { case 'i': case 'I': if (match(&s,"nf")) { --s; if (!match(&s,"inity")) ++s; word0(rv) = 0x7ff00000; word1(rv) = 0; goto ret; } break; case 'n': case 'N': if (match(&s, "an")) { word0(rv) = NAN_WORD0; word1(rv) = NAN_WORD1;#ifndef No_Hex_NaN if (*s == '(') /*)*/ hexnan(&rv, &s);#endif goto ret; } }#endif /* INFNAN_CHECK */ret0: s = s00; sign = 0; } goto ret; } e1 = e -= nf; /* Now we have nd0 digits, starting at s0, followed by a * decimal point, followed by nd-nd0 digits. The number we're * after is the integer represented by those digits times * 10**e */ if (!nd0) nd0 = nd; k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; dval(rv) = y; if (k > 9) {#ifdef SET_INEXACT if (k > DBL_DIG) oldinexact = get_inexact();#endif dval(rv) = tens[k - 9] * dval(rv) + z; } bd0 = 0; if (nd <= DBL_DIG && Flt_Rounds == 1) { if (!e) goto ret; if (e > 0) { if (e <= Ten_pmax) { /* rv = */ rounded_product(dval(rv), tens[e]); goto ret; } i = DBL_DIG - nd; if (e <= Ten_pmax + i) { /* A fancier test would sometimes let us do * this for larger i values. */ e -= i; dval(rv) *= tens[i]; /* rv = */ rounded_product(dval(rv), tens[e]); goto ret; } }#ifndef Inaccurate_Divide else if (e >= -Ten_pmax) { /* rv = */ rounded_quotient(dval(rv), tens[-e]); goto ret; }#endif } e1 += nd - k;#ifdef SET_INEXACT inexact = 1; if (k <= DBL_DIG) oldinexact = get_inexact();#endif#ifdef Avoid_Underflow scale = 0;#endif /* Get starting approximation = rv * 10**e1 */ if (e1 > 0) { if ((i = e1 & 15)) dval(rv) *= tens[i]; if (e1 &= ~15) { if (e1 > DBL_MAX_10_EXP) {ovfl:#ifndef NO_ERRNO errno = ERANGE;#endif /* Can't trust HUGE_VAL */ word0(rv) = Exp_mask; word1(rv) = 0;#ifdef SET_INEXACT /* set overflow bit */ dval(rv0) = 1e300; dval(rv0) *= dval(rv0);#endif if (bd0) goto retfree; goto ret; } e1 >>= 4; for (j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) dval(rv) *= bigtens[j]; /* The last multiplication could overflow. */ word0(rv) -= P * Exp_msk1; dval(rv) *= bigtens[j]; if ((z = word0(rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P)) goto ovfl; if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) { /* set to largest number */ /* (Can't trust DBL_MAX) */ word0(rv) = Big0; word1(rv) = Big1; } else word0(rv) += P * Exp_msk1; } } else if (e1 < 0) { e1 = -e1; if ((i = e1 & 15)) dval(rv) /= tens[i]; if (e1 >>= 4) { if (e1 >= 1 << n_bigtens) goto undfl;#ifdef Avoid_Underflow if (e1 & Scale_Bit) scale = 2 * P; for (j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) dval(rv) *= tinytens[j]; if (scale && (j = (2 * P) + 1 - ((word0(rv) & Exp_mask) >> Exp_shift)) > 0) { /* scaled rv is denormal; zap j low bits */ if (j >= 32) { word1(rv) = 0; if (j >= 53) word0(rv) = (P + 2) * Exp_msk1; else word0(rv) &= 0xffffffff << j - 32; } else word1(rv) &= 0xffffffff << j; }#else for (j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) dval(rv) *= tinytens[j]; /* The last multiplication could underflow. */ dval(rv0) = dval(rv); dval(rv) *= tinytens[j]; if (!dval(rv)) { dval(rv) = 2. * dval(rv0); dval(rv) *= tinytens[j];#endif if (!dval(rv)) {undfl: dval(rv) = 0.;#ifndef NO_ERRNO errno = ERANGE;#endif if (bd0) goto retfree; goto ret; }#ifndef Avoid_Underflow word0(rv) = Tiny0; word1(rv) = Tiny1; /* The refinement below will clean * this approximation up. */ }#endif } } /* Now the hard part -- adjusting rv to the correct value.*/ /* Put digits into bd: true value = bd * 10^e */ bd0 = s2b(s0, nd0, nd, y); for (;;) { bd = Balloc(bd0->k); Bcopy(bd, bd0); bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ bs = i2b(1); if (e >= 0) { bb2 = bb5 = 0; bd2 = bd5 = e; } else { bb2 = bb5 = -e; bd2 = bd5 = 0; } if (bbe >= 0) bb2 += bbe; else bd2 -= bbe; bs2 = bb2;#ifdef Avoid_Underflow j = bbe - scale; i = j + bbbits - 1; /* logb(rv) */ if (i < Emin) /* denormal */ j += P - Emin; else j = P + 1 - bbbits;#else /*Avoid_Underflow*/#ifdef Sudden_Underflow j = P + 1 - bbbits;#else /*Sudden_Underflow*/ j = bbe; i = j + bbbits - 1; /* logb(rv) */ if (i < Emin) /* denormal */ j += P - Emin; else j = P + 1 - bbbits;#endif /*Sudden_Underflow*/#endif /*Avoid_Underflow*/ bb2 += j; bd2 += j;#ifdef Avoid_Underflow bd2 += scale;#endif i = bb2 < bd2 ? bb2 : bd2; if (i > bs2) i = bs2; if (i > 0) { bb2 -= i; bd2 -= i; bs2 -= i; } if (bb5 > 0) { bs = pow5mult(bs, bb5); bb1 = mult(bs, bb); Bfree(bb); bb = bb1; } if (bb2 > 0) bb = lshift(bb, bb2); if (bd5 > 0) bd = pow5mult(bd, bd5); if (bd2 > 0) bd = lshift(bd, bd2); if (bs2 > 0) bs = lshift(bs, bs2); delta = diff(bb, bd); dsign = delta->sign; delta->sign = 0; i = cmp(delta, bs); if (i < 0) { /* Error is less than half an ulp -- check for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -