📄 dtoa.cpp
字号:
#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 Honor_FLT_ROUNDS if (rounding != 1) bs2++;#endif#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#ifdef IBM j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);#else j = P + 1 - bbbits;#endif#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);#ifdef Honor_FLT_ROUNDS if (rounding != 1) { if (i < 0) { /* Error is less than an ulp */ if (!delta->x[0] && delta->wds <= 1) { /* exact */#ifdef SET_INEXACT inexact = 0;#endif break; } if (rounding) { if (dsign) { adj = 1.; goto apply_adj; } } else if (!dsign) { adj = -1.; if (!word1(rv) && !(word0(rv) & Frac_mask)) { y = word0(rv) & Exp_mask;#ifdef Avoid_Underflow if (!scale || y > 2*P*Exp_msk1)#else if (y)#endif { delta = lshift(delta,Log2P); if (cmp(delta, bs) <= 0) adj = -0.5; } } apply_adj:#ifdef Avoid_Underflow if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) word0(adj) += (2*P+1)*Exp_msk1 - y;#else#ifdef Sudden_Underflow if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { word0(rv) += P*Exp_msk1; dval(rv) += adj*ulp(dval(rv)); word0(rv) -= P*Exp_msk1; } else#endif /*Sudden_Underflow*/#endif /*Avoid_Underflow*/ dval(rv) += adj*ulp(dval(rv)); } break; } adj = ratio(delta, bs); if (adj < 1.) adj = 1.; if (adj <= 0x7ffffffe) { /* adj = rounding ? ceil(adj) : floor(adj); */ y = adj; if (y != adj) { if (!((rounding>>1) ^ dsign)) y++; adj = y; } }#ifdef Avoid_Underflow if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) word0(adj) += (2*P+1)*Exp_msk1 - y;#else#ifdef Sudden_Underflow if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { word0(rv) += P*Exp_msk1; adj *= ulp(dval(rv)); if (dsign) dval(rv) += adj; else dval(rv) -= adj; word0(rv) -= P*Exp_msk1; goto cont; }#endif /*Sudden_Underflow*/#endif /*Avoid_Underflow*/ adj *= ulp(dval(rv)); if (dsign) dval(rv) += adj; else dval(rv) -= adj; goto cont; }#endif /*Honor_FLT_ROUNDS*/ 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 IEEE_Arith#ifdef Avoid_Underflow || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1#else || (word0(rv) & Exp_mask) <= Exp_msk1#endif#endif ) {#ifdef SET_INEXACT if (!delta->x[0] && delta->wds <= 1) inexact = 0;#endif break; } if (!delta->x[0] && delta->wds <= 1) { /* exact result */#ifdef SET_INEXACT inexact = 0;#endif 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) == (#ifdef Avoid_Underflow (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :#endif 0xffffffff)) { /*boundary case -- increment exponent*/ word0(rv) = (word0(rv) & Exp_mask) + Exp_msk1#ifdef IBM | Exp_msk1 >> 4#endif ; word1(rv) = 0;#ifdef Avoid_Underflow dsign = 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#ifdef Avoid_Underflow if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))#else if (L <= Exp_msk1)#endif /*Avoid_Underflow*/#endif /*IBM*/ goto undfl; L -= Exp_msk1;#else /*Sudden_Underflow}{*/#ifdef Avoid_Underflow if (scale) { L = word0(rv) & Exp_mask; if (L <= (2*P+1)*Exp_msk1) { if (L > (P+2)*Exp_msk1) /* round even ==> */ /* accept rv */ break; /* rv = smallest denormal */ goto undfl; } }#endif /*Avoid_Underflow*/ L = (word0(rv) & Exp_mask) - Exp_msk1;#endif /*Sudden_Underflow}}*/ 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) dval(rv) += ulp(dval(rv));#ifndef ROUND_BIASED else { dval(rv) -= ulp(dval(rv));#ifndef Sudden_Underflow if (!dval(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(Rounding) { 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 /*Check_FLT_ROUNDS*/ } y = word0(rv) & Exp_mask; /* Check for overflow */ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { dval(rv0) = dval(rv); word0(rv) -= P*Exp_msk1; adj = aadj1 * ulp(dval(rv)); dval(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 Avoid_Underflow if (scale && y <= 2*P*Exp_msk1) { if (aadj <= 0x7fffffff) { if ((z = (ULong)aadj) <= 0) z = 1; aadj = z; aadj1 = dsign ? aadj : -aadj; } word0(aadj1) += (2*P+1)*Exp_msk1 - y; } adj = aadj1 * ulp(dval(rv)); dval(rv) += adj;#else#ifdef Sudden_Underflow if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { dval(rv0) = dval(rv); word0(rv) += P*Exp_msk1; adj = aadj1 * ulp(dval(rv)); dval(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(dval(rv)); dval(rv) += adj; }#else /*Sudden_Underflow*/ /* 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(dval(rv)); dval(rv) += adj;#endif /*Sudden_Underflow*/#endif /*Avoid_Underflow*/ } z = word0(rv) & Exp_mask;#ifndef SET_INEXACT#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; }#endif cont: Bfree(bb); Bfree(bd); Bfree(bs); Bfree(delta); }#ifdef SET_INEXACT if (inexact) { if (!oldinexact) { word0(rv0) = Exp_1 + (70 << Exp_shift); word1(rv0) = 0; dval(rv0) += 1.; } } else if (!oldinexact) clear_inexact();#endif#ifdef Avoid_Underflow if (scale) { word0(rv0) = Exp_1 - 2*P*Exp_msk1; word1(rv0) = 0; dval(rv) *= dval(rv0);#ifndef NO_ERRNO /* try to avoid the bug of testing an 8087 register value */ if (word0(rv) == 0 && word1(rv) == 0) errno = ERANGE;#endif }#endif /* Avoid_Underflow */#ifdef SET_INEXACT if (inexact && !(word0(rv) & Exp_mask)) { /* set underflow bit */ dval(rv0) = 1e-300; dval(rv0) *= dval(rv0); }#endif retfree: Bfree(bb); Bfree(bd); Bfree(bs); Bfree(bd0); Bfree(delta); ret: if (se) *se = (char *)s; return sign ? -dval(rv) : dval(rv); } static intquorem#ifdef KR_headers (b, S) Bigint *b, *S;#else (Bigint *b, Bigint *S)#endif{ int n; ULong *bx, *bxe, q, *sx, *sxe;#ifdef ULLong ULLong borrow, carry, y, ys;#else ULong borrow, carry, y, ys;#ifdef Pack_32 ULong si, z, zs;#endif#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 ULLong ys = *sx++ * (ULLong)q + carry; carry = ys >> 32; y = *bx - (ys & FFFFFFFF) - borrow; borrow = y >> 32 & (ULong)1; *bx++ = y & FFFFFFFF;#else#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 = (y & 0x10000) >> 16; z = (*bx >> 16) - (zs & 0xffff) - borrow; borrow = (z & 0x10000) >> 16; Storeinc(bx, z, y);#else ys = *sx++ * q + carry; carry = ys >> 16; y = *bx - (ys & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; *bx++ = y & 0xffff;#endif#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 ULLong ys = *sx++ + carry; carry = ys >> 32; y = *bx - (ys & FFFFFFFF) - borrow; borrow = y >> 32 & (ULong)1; *bx++ = y & FFFFFFFF;#else#ifdef Pack_32 si = *sx++; ys = (si & 0xffff) + carry; zs = (si >> 16) + (ys >> 16); carry = zs >> 16; y = (*bx & 0xffff) - (ys & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; z = (*bx >> 16) - (zs & 0xffff) - borrow; borrow = (z & 0x10000) >> 16; Storeinc(bx, z, y);#else ys = *sx++ + carry; carry = ys >> 16; y = *bx - (ys & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; *bx++ = y & 0xffff;#endif#endif } while(sx <= sxe); bx = b->x; bxe = bx + n;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -