strtod.c
来自「用于嵌入式Linux系统的标准C的库函数」· C语言 代码 · 共 732 行 · 第 1/2 页
C
732 行
else word0 (rv) += P * Exp_msk1; } } } else if (e1 < 0) { e1 = -e1; if ((i = e1 & 15) != 0) rv.d /= tens[i]; if (e1 &= ~15) { e1 >>= 4; if (e1 >= 1 << n_bigtens) goto undfl; for (j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) rv.d *= tinytens[j]; /* The last multiplication could underflow. */ rv0.d = rv.d; rv.d *= tinytens[j]; if (!rv.d) { rv.d = 2. * rv0.d; rv.d *= tinytens[j]; if (!rv.d) { undfl: rv.d = 0.; ptr->_errno = ERANGE; if (bd0) goto retfree; goto ret; }#ifndef _DOUBLE_IS_32BITS word0 (rv) = Tiny0; word1 (rv) = Tiny1;#else word0 (rv) = Tiny1;#endif /* 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 (ptr, s0, nd0, nd, y); for (;;) { bd = Balloc (ptr, bd0->_k); Bcopy (bd, bd0); bb = d2b (ptr, rv.d, &bbe, &bbbits); /* rv.d = bb * 2^bbe */ bs = i2b (ptr, 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.d) */ 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 (ptr, bs, bb5); bb1 = mult (ptr, bs, bb); Bfree (ptr, bb); bb = bb1; } if (bb2 > 0) bb = lshift (ptr, bb, bb2); if (bd5 > 0) bd = pow5mult (ptr, bd, bd5); if (bd2 > 0) bd = lshift (ptr, bd, bd2); if (bs2 > 0) bs = lshift (ptr, bs, bs2); delta = diff (ptr, 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 (ptr, 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 ;#ifndef _DOUBLE_IS_32BITS word1 (rv) = 0;#endif 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;#ifndef _DOUBLE_IS_32BITS word1 (rv) = 0xffffffff;#endif#ifdef IBM goto cont;#else break;#endif }#ifndef ROUND_BIASED if (!(word1 (rv) & LSB)) break;#endif if (dsign) rv.d += ulp (rv.d);#ifndef ROUND_BIASED else { rv.d -= ulp (rv.d);#ifndef Sudden_Underflow if (!rv.d) 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)) { rv0.d = rv.d; word0 (rv) -= P * Exp_msk1; adj = aadj1 * ulp (rv.d); rv.d += adj; if ((word0 (rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) { if (word0 (rv0) == Big0 && word1 (rv0) == Big1) goto ovfl;#ifdef _DOUBLE_IS_32BITS word0 (rv) = Big1;#else word0 (rv) = Big0; word1 (rv) = Big1;#endif goto cont; } else word0 (rv) += P * Exp_msk1; } else {#ifdef Sudden_Underflow if ((word0 (rv) & Exp_mask) <= P * Exp_msk1) { rv0.d = rv.d; word0 (rv) += P * Exp_msk1; adj = aadj1 * ulp (rv.d); rv.d += 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 (rv.d); rv.d += adj; }#else /* Compute adj so that the IEEE rounding rules will * correctly round rv.d + adj in some half-way cases. * If rv.d * ulp(rv.d) 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 (rv.d); rv.d += 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 (ptr, bb); Bfree (ptr, bd); Bfree (ptr, bs); Bfree (ptr, delta); }retfree: Bfree (ptr, bb); Bfree (ptr, bd); Bfree (ptr, bs); Bfree (ptr, bd0); Bfree (ptr, delta);ret: if (se) *se = (char *) s; return sign ? -rv.d : rv.d;}#ifndef NO_REENTdouble_DEFUN (strtod, (s00, se), _CONST char *s00 _AND char **se){ return _strtod_r (_REENT, s00, se);}float_DEFUN (strtof, (s00, se), _CONST char *s00 _AND char **se){ return (float)_strtod_r (_REENT, s00, se);}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?