📄 jsdtoa.c
字号:
#ifdef __STDC__ rv = HUGE_VAL;#else /* Can't trust HUGE_VAL */ set_word0(rv, Exp_mask); set_word1(rv, 0);#endif if (bd0) goto retfree; goto ret; } e1 >>= 4; for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) rv *= bigtens[j]; /* The last multiplication could overflow. */ set_word0(rv, word0(rv) - P*Exp_msk1); 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) */ set_word0(rv, Big0); set_word1(rv, Big1); } else set_word0(rv, word0(rv) + P*Exp_msk1); } } else if (e1 < 0) { e1 = -e1; if ((i = e1 & 15) != 0) rv /= tens[i]; if (e1 &= ~15) { e1 >>= 4; if (e1 >= 1 << n_bigtens) goto undfl;#ifdef Avoid_Underflow if (e1 & Scale_Bit) scale = P; for(j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) rv *= tinytens[j]; if (scale && (j = P + 1 - ((word0(rv) & Exp_mask) >> Exp_shift)) > 0) { /* scaled rv is denormal; zap j low bits */ if (j >= 32) { set_word1(rv, 0); set_word0(rv, word0(rv) & (0xffffffff << (j-32))); if (!word0(rv)) set_word0(rv, 1); } else set_word1(rv, word1(rv) & (0xffffffff << j)); }#else for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) rv *= tinytens[j]; /* The last multiplication could underflow. */ rv0 = rv; rv *= tinytens[j]; if (!rv) { rv = 2.*rv0; rv *= tinytens[j];#endif if (!rv) { undfl: rv = 0.; *err = JS_DTOA_ERANGE; if (bd0) goto retfree; goto ret; }#ifndef Avoid_Underflow set_word0(rv, Tiny0); set_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); if (!bd0) goto nomem; for(;;) { bd = Balloc(bd0->k); if (!bd) goto nomem; Bcopy(bd, bd0); bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ if (!bb) goto nomem; bs = i2b(1); if (!bs) goto nomem; 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 j = P + 1 - bbbits;#else#ifdef Avoid_Underflow j = bbe - scale;#else j = bbe;#endif i = j + bbbits - 1; /* logb(rv) */ if (i < Emin) /* denormal */ j += P - Emin; else j = P + 1 - bbbits;#endif 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); if (!bs) goto nomem; bb1 = mult(bs, bb); if (!bb1) goto nomem; Bfree(bb); bb = bb1; } if (bb2 > 0) { bb = lshift(bb, bb2); if (!bb) goto nomem; } if (bd5 > 0) { bd = pow5mult(bd, bd5); if (!bd) goto nomem; } if (bd2 > 0) { bd = lshift(bd, bd2); if (!bd) goto nomem; } if (bs2 > 0) { bs = lshift(bs, bs2); if (!bs) goto nomem; } delta = diff(bb, bd); if (!delta) goto nomem; 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#ifdef Avoid_Underflow || (word0(rv) & Exp_mask) <= Exp_msk1 + P*Exp_msk1#else || (word0(rv) & Exp_mask) <= Exp_msk1#endif ) {#ifdef Avoid_Underflow if (!delta->x[0] && delta->wds == 1) dsign = 2;#endif break; } delta = lshift(delta,Log2P); if (!delta) goto nomem; 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*/ set_word0(rv, (word0(rv) & Exp_mask) + Exp_msk1); set_word1(rv, 0);#ifdef Avoid_Underflow dsign = 0;#endif break; } } else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {#ifdef Avoid_Underflow dsign = 2;#endif drop_down: /* boundary case -- decrement exponent */#ifdef Sudden_Underflow L = word0(rv) & Exp_mask; if (L <= Exp_msk1) goto undfl; L -= Exp_msk1;#else L = (word0(rv) & Exp_mask) - Exp_msk1;#endif set_word0(rv, L | Bndry_mask1); set_word1(rv, 0xffffffff); break; }#ifndef ROUND_BIASED if (!(word1(rv) & LSB)) break;#endif if (dsign) rv += ulp(rv);#ifndef ROUND_BIASED else { rv -= ulp(rv);#ifndef Sudden_Underflow if (!rv) goto undfl;#endif }#ifdef Avoid_Underflow dsign = 1 - dsign;#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 = rv; set_word0(rv, word0(rv) - P*Exp_msk1); adj = aadj1 * ulp(rv); rv += adj; if ((word0(rv) & Exp_mask) >= Exp_msk1*(DBL_MAX_EXP+Bias-P)) { if (word0(rv0) == Big0 && word1(rv0) == Big1) goto ovfl; set_word0(rv, Big0); set_word1(rv, Big1); goto cont; } else set_word0(rv, word0(rv) + P*Exp_msk1); } else {#ifdef Sudden_Underflow if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { rv0 = rv; set_word0(rv, word0(rv) + P*Exp_msk1); adj = aadj1 * ulp(rv); rv += adj; if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1) goto undfl; set_word0(rv, Tiny0); set_word1(rv, Tiny1); goto cont; } else set_word0(rv, word0(rv) - P*Exp_msk1); } else { adj = aadj1 * ulp(rv); 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 . */#ifdef Avoid_Underflow if (y <= P*Exp_msk1 && aadj > 1.)#else if (y <= (P-1)*Exp_msk1 && aadj > 1.)#endif { aadj1 = (double)(int32)(aadj + 0.5); if (!dsign) aadj1 = -aadj1; }#ifdef Avoid_Underflow if (scale && y <= P*Exp_msk1) set_word0(aadj1, word0(aadj1) + (P+1)*Exp_msk1 - y);#endif adj = aadj1 * ulp(rv); rv += adj;#endif } z = word0(rv) & Exp_mask;#ifdef Avoid_Underflow if (!scale)#endif if (y == z) { /* Can we stop now? */ L = (Long)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); bb = bd = bs = delta = NULL; }#ifdef Avoid_Underflow if (scale) { rv0 = 0.; set_word0(rv0, Exp_1 - P*Exp_msk1); set_word1(rv0, 0); if ((word0(rv) & Exp_mask) <= P*Exp_msk1 && word1(rv) & 1 && dsign != 2) { if (dsign) {#ifdef Sudden_Underflow /* rv will be 0, but this would give the */ /* right result if only rv *= rv0 worked. */ set_word0(rv, word0(rv) + P*Exp_msk1); set_word0(rv0, Exp_1 - 2*P*Exp_msk1);#endif rv += ulp(rv); } else set_word1(rv, word1(rv) & ~1); } rv *= rv0; }#endif /* Avoid_Underflow */retfree: Bfree(bb); Bfree(bd); Bfree(bs); Bfree(bd0); Bfree(delta);ret: RELEASE_DTOA_LOCK(); if (se) *se = (char *)s; return sign ? -rv : rv;nomem: Bfree(bb); Bfree(bd); Bfree(bs); Bfree(bd0); Bfree(delta); RELEASE_DTOA_LOCK(); *err = JS_DTOA_ENOMEM; return 0;}/* Return floor(b/2^k) and set b to be the remainder. The returned quotient must be less than 2^32. */static uint32 quorem2(Bigint *b, int32 k){ ULong mask; ULong result; ULong *bx, *bxe; int32 w; int32 n = k >> 5; k &= 0x1F; mask = (1<<k) - 1; w = b->wds - n; if (w <= 0) return 0; JS_ASSERT(w <= 2); bx = b->x; bxe = bx + n; result = *bxe >> k; *bxe &= mask; if (w == 2) { JS_ASSERT(!(bxe[1] & ~mask)); if (k) result |= bxe[1] << (32 - k); } n++; while (!*bxe && bxe != bx) { n--; bxe--; } b->wds = n; return result;}/* Return floor(b/S) and set b to be the remainder. As added restrictions, b must not have * more words than S, the most significant word of S must not start with a 1 bit, and the * returned quotient must be less than 36. */static int32 quorem(Bigint *b, Bigint *S){ int32 n; ULong *bx, *bxe, q, *sx, *sxe;#ifdef ULLong ULLong borrow, carry, y, ys;#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -