⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prdtoa.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 4 页
字号:
				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 = (PRInt32)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;	rv = y;	if (k > 9)		rv = tens[k - 9] * 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				/* rv = */ rounded_product(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;				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;				/* rv = */ rounded_product(rv, tens[e]);				if ((word0(rv) & Exp_mask)					> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))					goto ovfl;				word0(rv) += P*Exp_msk1;#else				/* rv = */ rounded_product(rv, tens[e]);#endif				goto ret;			}		}#ifndef Inaccurate_Divide		else if (e >= -Ten_pmax) {			/* rv = */ rounded_quotient(rv, tens[-e]);			goto ret;		}#endif	}	e1 += nd - k;	/* Get starting approximation = rv * 10**e1 */	if (e1 > 0) {		if ((i = e1 & 15) != 0)			rv *= tens[i];		if (e1 &= ~15) {			if (e1 > DBL_MAX_10_EXP) {			ovfl:				PR_SetError(PR_RANGE_ERROR, 0);#ifdef __STDC__				rv = HUGE_VAL;#else				/* Can't trust HUGE_VAL */#ifdef IEEE_Arith				word0(rv) = Exp_mask;				word1(rv) = 0;#else				word0(rv) = Big0;				word1(rv) = Big1;#endif#endif				if (bd0)					goto retfree;				goto ret;			}			if (e1 >>= 4) {				for(j = 0; e1 > 1; j++, e1 >>= 1)					if (e1 & 1)						rv *= bigtens[j];				/* The last multiplication could overflow. */				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) */					word0(rv) = Big0;					word1(rv) = Big1;				}				else					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;			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];				if (!rv) {				undfl:					rv = 0.;					PR_SetError(PR_RANGE_ERROR, 0);					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(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 = (long)((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)				rv += ulp(rv);#ifndef ROUND_BIASED			else {				rv -= ulp(rv);#ifndef Sudden_Underflow				if (!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)) {			rv0 = 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;				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) {				rv0 = rv;				word0(rv) += P*Exp_msk1;				adj = aadj1 * ulp(rv);				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(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 .			 */			if (y <= (P-1)*Exp_msk1 && aadj >= 1.) {				aadj1 = (double)(PRInt32)(aadj + 0.5);				if (!dsign)					aadj1 = -aadj1;			}			adj = aadj1 * ulp(rv);			rv += adj;#endif		}		z = word0(rv) & Exp_mask;		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);	}retfree:	Bfree(bb);	Bfree(bd);	Bfree(bs);	Bfree(bd0);	Bfree(delta);ret:	if (se)		*se = (char *)s;	return sign ? -rv : rv;}static PRInt32quorem(Bigint *b, Bigint *S){	PRInt32 n;	Long borrow, y;	unsigned Long carry, q, ys;	unsigned Long *bx, *bxe, *sx, *sxe;#ifdef Pack_32	Long z;	unsigned Long si, zs;#endif	n = S->wds;#ifdef DEBUG_DTOA	/*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_DTOA	/*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 = (long)((*bx & 0xffff) - (ys & 0xffff) + borrow);			borrow = y >> 16;			Sign_Extend(borrow, y);			z = (long)((*bx >> 16) - (zs & 0xffff) + borrow);			borrow = 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 = (long)((*bx & 0xffff) - (ys & 0xffff) + borrow);			borrow = y >> 16;			Sign_Extend(borrow, y);			z = (long)((*bx >> 16) - (zs & 0xffff) + borrow);			borrow = 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 (int)q;}/* PR_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. 112-126]. * * 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 *	   to get by with floating-point arithmetic; we resort to *	   multiple-precision integer arithmetic only if we cannot *	   guarantee that the floating-point calculation has given *	   the correctly rounded result.  For k requested digits and *	   "uniformly" distributed input, the probability is *	   something like 10^(k-15) that we must resort to the Long *	   calculation. */PR_IMPLEMENT(PRStatus)PR_dtoa(PRFloat64 d, int mode, int ndigits,	int *decpt, int *sign, char **rve, char *buf, PRSize bufsize){	/*	Arguments ndigits, decpt, sign are similar to those		of ecvt and fcvt; trailing zeros are suppressed from		the returned string.  If not null, *rve is set to point		to the end of the return value.  If d is +-Infinity or NaN,		then *decpt is set to 9999.		mode:		0 ==> shortest string that yields d when read in		and rounded to nearest.		1 ==> like 0, but with Steele & White stopping rule;		e.g. with IEEE P754 arithmetic , mode 0 gives		1e23 whereas mode 1 gives 9.999999999999999e22.		2 ==> max(1,ndigits) significant digits.  This gives a		return value similar to that of ecvt, except		that trailing zeros are suppressed.		3 ==> through ndigits past the decimal point.  This		gives a return value similar to that from fcvt,		except that trailing zeros are suppressed, and		ndigits can be negative.		4-9 should give the same return values as 2-3, i.e.,		4 <= mode <= 9 ==> same return as mode		2 + (mode & 1).  These modes are mainly for		debugging; often they run slower but sometimes		faster than modes 2-3.		4,5,8,9 ==> left-to-right digit generation.		6-9 ==> don't try fast floating-point estimate		(if applicable).		Values of mode other than 0-9 are treated as mode 0.		Sufficient space is allocated to the return value		to hold the suppressed trailing zeros.	*/	PRInt32 bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,		j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,		spec_case, try_quick;	Long L;#ifndef Sudden_Underflow	PRInt32 denorm;	unsigned Long x;#endif	Bigint *b, *b1, *delta, *mlo, *mhi, *S;	double d2, ds, eps;	char *s, *s0;	Bigint *result = 0;	PRInt32 result_k;	PRStatus retval;	PRSize strsize;	if (!_pr_initialized) _PR_ImplicitInitialization();	if (word0(d) & Sign_bit) {		/* set sign for everything, including 0's and NaNs */		*sign = 1;		word0(d) &= ~Sign_bit;	/* clear sign bit */	}	else		*sign = 0;#if defined(IEEE_Arith) + defined(VAX)#ifdef IEEE_Arith	if ((word0(d) & Exp_mask) == Exp_mask)#else		if (word0(d)  == 0x8000)#endif			{				/* Infinity or NaN */				*decpt = 9999;				s =#ifdef IEEE_Arith					!word1(d) && !(word0(d) & 0xfffff) ? "Infinity" :#endif					"NaN";

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -