📄 strtod.c
字号:
else s = s0; /* ... otherwise go back. */ } goto ret; } 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 == decimal_point) { 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) { s = s00; goto ret; } s00 = s; esign = 0; switch(c = *++s) { case '-': esign = 1; /* FALLTHROUGH */ 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) s = s00; 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; value(rv) = y; if (k > 9) value(rv) = tens[k - 9] * value(rv) + z; bd0 = 0; if (nd <= DBL_DIG#ifndef RND_PRODQUOT && FLT_ROUNDS == 1#endif ) { if (!e) goto ret; if (e > 0) { if (e <= Ten_pmax) {#ifdef VAX goto vax_ovfl_check;#else /* value(rv) = */ rounded_product(value(rv), tens[e]); goto ret;#endif } i = DBL_DIG - nd; if (e <= Ten_pmax + i) { /* A fancier test would sometimes let us do * this for larger i values. */ e -= i; value(rv) *= tens[i];#ifdef VAX /* VAX exponent range is so narrow we must * worry about overflow here... */ vax_ovfl_check: word0(rv) -= P*Exp_msk1; /* value(rv) = */ rounded_product(value(rv), tens[e]); if ((word0(rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) goto ovfl; word0(rv) += P*Exp_msk1;#else /* value(rv) = */ rounded_product(value(rv), tens[e]);#endif goto ret; } }#ifndef Inaccurate_Divide else if (e >= -Ten_pmax) { /* value(rv) = */ rounded_quotient(value(rv), tens[-e]); goto ret; }#endif } e1 += nd - k; /* Get starting approximation = rv * 10**e1 */ if (e1 > 0) { if ((i = e1 & 15) != 0) value(rv) *= tens[i]; if (e1 &= ~15) { if (e1 > DBL_MAX_10_EXP) { ovfl: errno = ERANGE; value(rv) = HUGE_VAL; if (bd0) goto retfree; goto ret; } if ((e1 = (unsigned int)e1 >> 4) != 0) { for(j = 0; e1 > 1; j++, e1 = (unsigned int)e1 >> 1) if (e1 & 1) value(rv) *= bigtens[j]; /* The last multiplication could overflow. */ word0(rv) -= P*Exp_msk1; value(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) != 0) value(rv) /= tens[i]; if (e1 &= ~15) { e1 = (unsigned int)e1 >> 4; if (e1 >= 1 << n_bigtens) goto undfl; for(j = 0; e1 > 1; j++, e1 = (unsigned int)e1 >> 1) if (e1 & 1) value(rv) *= tinytens[j]; /* The last multiplication could underflow. */ value(rv0) = value(rv); value(rv) *= tinytens[j]; if (!value(rv)) { value(rv) = 2.*value(rv0); value(rv) *= tinytens[j]; if (!value(rv)) { undfl: value(rv) = 0.; errno = ERANGE; if (bd0) goto retfree; goto ret; } word0(rv) = Tiny0; word1(rv) = Tiny1; /* The refinement below will clean * this approximation up. */ } } } /* 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(value(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 Sudden_Underflow#ifdef IBM j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);#else j = P + 1 - bbbits;#endif#else i = bbe + bbbits - 1; /* logb(rv) */ if (i < Emin) /* denormal */ j = bbe + (P-Emin); else j = P + 1 - bbbits;#endif bb2 += j; bd2 += j; 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 * special case of mantissa a power of two. */ if (dsign || word1(rv) || word0(rv) & Bndry_mask) break; delta = lshift(delta,Log2P); if (cmp(delta, bs) > 0) goto drop_down; break; } if (i == 0) { /* exactly half-way between */ if (dsign) { if ((word0(rv) & Bndry_mask1) == Bndry_mask1 && word1(rv) == 0xffffffff) { /*boundary case -- increment exponent*/ word0(rv) = (word0(rv) & Exp_mask) + Exp_msk1#ifdef IBM | Exp_msk1 >> 4#endif ; word1(rv) = 0; break; } } else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { drop_down: /* boundary case -- decrement exponent */#ifdef Sudden_Underflow L = word0(rv) & Exp_mask;#ifdef IBM if (L < Exp_msk1)#else if (L <= Exp_msk1)#endif goto undfl; L -= Exp_msk1;#else L = (word0(rv) & Exp_mask) - Exp_msk1;#endif word0(rv) = L | Bndry_mask1; word1(rv) = 0xffffffff;#ifdef IBM goto cont;#else break;#endif }#ifndef ROUND_BIASED if (!(word1(rv) & LSB)) break;#endif if (dsign) value(rv) += ulp(value(rv));#ifndef ROUND_BIASED else { value(rv) -= ulp(value(rv));#ifndef Sudden_Underflow if (!value(rv)) goto undfl;#endif }#endif break; } if ((aadj = ratio(delta, bs)) <= 2.) { if (dsign) aadj = aadj1 = 1.; else if (word1(rv) || word0(rv) & Bndry_mask) {#ifndef Sudden_Underflow if (word1(rv) == Tiny1 && !word0(rv)) goto undfl;#endif aadj = 1.; aadj1 = -1.; } else { /* special case -- power of FLT_RADIX to be */ /* rounded down... */ if (aadj < 2./FLT_RADIX) aadj = 1./FLT_RADIX; else aadj *= 0.5; aadj1 = -aadj; } } else { aadj *= 0.5; aadj1 = dsign ? aadj : -aadj;#ifdef Check_FLT_ROUNDS switch(FLT_ROUNDS) { case 2: /* towards +infinity */ aadj1 -= 0.5; break; case 0: /* towards 0 */ case 3: /* towards -infinity */ aadj1 += 0.5; }#else if (FLT_ROUNDS == 0) aadj1 += 0.5;#endif } y = word0(rv) & Exp_mask; /* Check for overflow */ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { value(rv0) = value(rv); word0(rv) -= P*Exp_msk1; adj = aadj1 * ulp(value(rv)); value(rv) += adj; if ((word0(rv) & Exp_mask) >= Exp_msk1*(DBL_MAX_EXP+Bias-P)) { if (word0(rv0) == Big0 && word1(rv0) == Big1) goto ovfl; word0(rv) = Big0; word1(rv) = Big1; goto cont; } else word0(rv) += P*Exp_msk1; } else {#ifdef Sudden_Underflow if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { value(rv0) = value(rv); word0(rv) += P*Exp_msk1; adj = aadj1 * ulp(value(rv)); value(rv) += adj;#ifdef IBM if ((word0(rv) & Exp_mask) < P*Exp_msk1)#else if ((word0(rv) & Exp_mask) <= P*Exp_msk1)#endif { if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1) goto undfl; word0(rv) = Tiny0; word1(rv) = Tiny1; goto cont; } else word0(rv) -= P*Exp_msk1; } else { adj = aadj1 * ulp(value(rv)); value(rv) += adj; }#else /* Compute adj so that the IEEE rounding rules will * correctly round rv + adj in some half-way cases. * If rv * ulp(rv) is denormalized (i.e., * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid * trouble from bits lost to denormalization; * example: 1.2e-307 . */ if (y <= (P-1)*Exp_msk1 && aadj >= 1.) { aadj1 = (double)(int)(aadj + 0.5); if (!dsign) aadj1 = -aadj1; } adj = aadj1 * ulp(value(rv)); value(rv) += adj;#endif } z = word0(rv) & Exp_mask; if (y == z) { /* Can we stop now? */ L = aadj; aadj -= L; /* The tolerances below are conservative. */ if (dsign || word1(rv) || word0(rv) & Bndry_mask) { if (aadj < .4999999 || aadj > .5000001) break; } else if (aadj < .4999999/FLT_RADIX) break; } cont: Bfree(bb); Bfree(bd); Bfree(bs); Bfree(delta); } retfree: Bfree(bb); Bfree(bd); Bfree(bs); Bfree(bd0); Bfree(delta); ret: if (se) /* LINTED interface specification */ *se = (char *)s; return sign ? -value(rv) : value(rv); } static intquorem#ifdef KR_headers (b, S) Bigint *b, *S;#else (Bigint *b, Bigint *S)#endif{ int n; Long borrow, y; ULong carry, q, ys; ULong *bx, *bxe, *sx, *sxe;#ifdef Pack_32 Long z; ULong si, zs;#endif n = S->wds;#ifdef DEBUG /*debug*/ if (b->wds > n) /*debug*/ Bug("oversize b in quorem");#endif if (b->wds < n) return 0; sx = S->x; sxe = sx + --n; bx = b->x; bxe = bx + n; q = *bxe / (*sxe + 1); /* ensure q <= true quotient */#ifdef DEBUG /*debug*/ if (q > 9) /*debug*/ Bug("oversized quotient in quorem");#endif if (q) { borrow = 0; carry = 0; do {#ifdef Pack_32 si = *sx++; ys = (si & 0xffff) * q + carry; zs = (si >> 16) * q + (ys >> 16); carry = zs >> 16; y = (*bx & 0xffff) - (ys & 0xffff) + borrow; borrow = (ULong)y >> 16; Sign_Extend(borrow, y); z = (*bx >> 16) - (zs & 0xffff) + borrow; borrow = (ULong)z >> 16; Sign_Extend(borrow, z); Storeinc(bx, z, y);#else ys = *sx++ * q + carry; carry = ys >> 16; y = *bx - (ys & 0xffff) + borrow; borrow = y >> 16; Sign_Extend(borrow, y); *bx++ = y & 0xffff;#endif } while(sx <= sxe); if (!*bxe) { bx = b->x; while(--bxe > bx && !*bxe) --n; b->wds = n; } } if (cmp(b, S) >= 0) { q++; borrow = 0; carry = 0; bx = b->x; sx = S->x; do {#ifdef Pack_32 si = *sx++; ys = (si & 0xffff) + carry; zs = (si >> 16) + (ys >> 16); carry = zs >> 16; y = (*bx & 0xffff) - (ys & 0xffff) + borrow; borrow = (ULong)y >> 16; Sign_Extend(borrow, y); z = (*bx >> 16) - (zs & 0xffff) + borrow; borrow = (ULong)z >> 16; Sign_Extend(borrow, z); Storeinc(bx, z, y);#else ys = *sx++ + carry; carry = ys >> 16; y = *bx - (ys & 0xffff) + borrow; borrow = y >> 16; Sign_Extend(borrow, y); *bx++ = y & 0xffff;#endif } while(sx <= sxe); bx = b->x; bxe = bx + n; if (!*bxe) { while(--bxe > bx && !*bxe) --n; b->wds = n; } } return q; }/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. * * Inspired by "How to Print Floating-Point Numbers Accurately" by * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101]. * * Modifications: * 1. Rather than iterating, we use a simple numeric overestimate * to determine k = floor(log10(d)). We scale relevant * quantities using O(log2(k)) rather than O(k) multiplications. * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't * try to generate digits strictly left to right. Instead, we * compute with fewer bits and propagate the carry if necessary * when rounding the final digit up. This is often faster. * 3. Under the assumption that input will be rounded nearest, * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. * That is, we allow equality in stopping tests when the * round-nearest rule will give the same floating-point value * as would satisfaction of the stopping test with strict * inequality. * 4. We remove common factors of powers of 2 from relevant * quantities. * 5. When converting floating-point integers less than 1e16, * we use floating-point arithmetic rather than resorting * to multiple-precision integers. * 6. When asked to produce fewer than 15 digits, we first try
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -