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

📄 ldtoa.c

📁 用于嵌入式Linux系统的标准C的库函数
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Mode 3 is "f" format.  */if( mode != 3 )        ndigits -= 1;/* Mode 0 is for %.999 format, which is supposed to give a   minimum length string that will convert back to the same binary value.   For now, just ask for 20 digits which is enough but sometimes too many.  */if( mode == 0 )        ndigits = 20;/* This sanity limit must agree with the corresponding one in etoasc, to   keep straight the returned value of outexpon.  */if( ndigits > NDEC )        ndigits = NDEC;etoasc( e, outbuf, ndigits, mode, ldp );s =  outbuf;if( eisinf(e) || eisnan(e) )        {        *decpt = 9999;        goto stripspaces;        }*decpt = ldp->outexpon + 1;/* Transform the string returned by etoasc into what the caller wants.  *//* Look for decimal point and delete it from the string. */s = outbuf;while( *s != '\0' )        {        if( *s == '.' )               goto yesdecpt;        ++s;        }goto nodecpt;yesdecpt:/* Delete the decimal point.  */while( *s != '\0' )        {        *s = *(s+1);        ++s;        }nodecpt:/* Back up over the exponent field. */while( *s != 'E' && s > outbuf)        --s;*s = '\0';stripspaces:/* Strip leading spaces and sign. */p = outbuf;while( *p == ' ' || *p == '-')        ++p;/* Find new end of string.  */s = outbuf;while( (*s++ = *p++) != '\0' )        ;--s;/* Strip trailing zeros.  */if( mode == 2 )        k = 1;else if( ndigits > ldp->outexpon )        k = ndigits;else        k = ldp->outexpon;while( *(s-1) == '0' && ((s - outbuf) > k))        *(--s) = '\0';/* In f format, flush small off-scale values to zero.   Rounding has been taken care of by etoasc. */if( mode == 3 && ((ndigits + ldp->outexpon) < 0))        {        s = outbuf;        *s = '\0';        *decpt = 0;        }/* reentrancy addition to use mprec storage pool *//* we want to have enough space to hold the formatted result */if (mode == 3) /* f format, account for sign + dec digits + decpt + frac */  i = *decpt + orig_ndigits + 3;else /* account for sign + max precision digs + E + exp sign + exponent */  i = orig_ndigits + MAX_EXP_DIGITS + 4;j = sizeof (__ULong);for (_REENT_MP_RESULT_K(ptr) = 0; sizeof (_Bigint) - sizeof (__ULong) + j <= i; j <<= 1)  _REENT_MP_RESULT_K(ptr)++;_REENT_MP_RESULT(ptr) = Balloc (ptr, _REENT_MP_RESULT_K(ptr));/* Copy from internal temporary buffer to permanent buffer.  */outstr = (char *)_REENT_MP_RESULT(ptr);strcpy (outstr, outbuf);if( rve )        *rve = outstr + (s - outbuf);return outstr;}/* Routine used to tell if long double is NaN or Infinity or regular number.    Returns:  0 = regular number             1 = Nan             2 = Infinity*/int_ldcheck (long double *d){unsigned short e[NI];LDPARMS rnd;LDPARMS *ldp = &rnd;rnd.rlast = -1;rnd.rndprc = NBITS;#if LDBL_MANT_DIG == 24e24toe( (unsigned short *)d, e, ldp );#elif LDBL_MANT_DIG == 53e53toe( (unsigned short *)d, e, ldp );#elif LDBL_MANT_DIG == 64e64toe( (unsigned short *)d, e, ldp );#elsee113toe( (unsigned short *)d, e, ldp );#endifif( (e[NE-1] & 0x7fff) == 0x7fff )	{#ifdef NANS	if( eisnan(e) )		return( 1 );#endif	return( 2 );	}else	return( 0 );} /* _ldcheck */static void etoasc(short unsigned int *x, char *string, int ndigits, int outformat, LDPARMS *ldp){long digit;unsigned short y[NI], t[NI], u[NI], w[NI];unsigned short *p, *r, *ten;unsigned short sign;int i, j, k, expon, rndsav, ndigs;char *s, *ss;unsigned short m;unsigned short *equot = ldp->equot;ndigs = ndigits;rndsav = ldp->rndprc;#ifdef NANSif( eisnan(x) )	{	sprintf( string, " NaN " );	expon = 9999;	goto bxit;	}#endifldp->rndprc = NBITS;		/* set to full precision */emov( x, y ); /* retain external format */if( y[NE-1] & 0x8000 )	{	sign = 0xffff;	y[NE-1] &= 0x7fff;	}else	{	sign = 0;	}expon = 0;ten = &etens[NTEN][0];emov( eone, t );/* Test for zero exponent */if( y[NE-1] == 0 )	{	for( k=0; k<NE-1; k++ )		{		if( y[k] != 0 )			goto tnzro; /* denormalized number */		}	goto isone; /* legal all zeros */	}tnzro:/* Test for infinity. */if( y[NE-1] == 0x7fff )	{	if( sign )		sprintf( string, " -Infinity " );	else		sprintf( string, " Infinity " );	expon = 9999;	goto bxit;	}/* Test for exponent nonzero but significand denormalized. * This is an error condition. */if( (y[NE-1] != 0) && ((y[NE-2] & 0x8000) == 0) )	{	mtherr( "etoasc", DOMAIN );	sprintf( string, "NaN" );	expon = 9999;	goto bxit;	}/* Compare to 1.0 */i = ecmp( eone, y );if( i == 0 )	goto isone;if( i < 0 )	{ /* Number is greater than 1 *//* Convert significand to an integer and strip trailing decimal zeros. */	emov( y, u );	u[NE-1] = EXONE + NBITS - 1;	p = &etens[NTEN-4][0];	m = 16;do	{	ediv( p, u, t, ldp );	efloor( t, w, ldp );	for( j=0; j<NE-1; j++ )		{		if( t[j] != w[j] )			goto noint;		}	emov( t, u );	expon += (int )m;noint:	p += NE;	m >>= 1;	}while( m != 0 );/* Rescale from integer significand */	u[NE-1] += y[NE-1] - (unsigned int )(EXONE + NBITS - 1);	emov( u, y );/* Find power of 10 */	emov( eone, t );	m = MAXP;	p = &etens[0][0];	while( ecmp( ten, u ) <= 0 )		{		if( ecmp( p, u ) <= 0 )			{			ediv( p, u, u, ldp );			emul( p, t, t, ldp );			expon += (int )m;			}		m >>= 1;		if( m == 0 )			break;		p += NE;		}	}else	{ /* Number is less than 1.0 *//* Pad significand with trailing decimal zeros. */	if( y[NE-1] == 0 )		{		while( (y[NE-2] & 0x8000) == 0 )			{			emul( ten, y, y, ldp );			expon -= 1;			}		}	else		{		emovi( y, w );		for( i=0; i<NDEC+1; i++ )			{			if( (w[NI-1] & 0x7) != 0 )				break;/* multiply by 10 */			emovz( w, u );			eshdn1( u );			eshdn1( u );			eaddm( w, u );			u[1] += 3;			while( u[2] != 0 )				{				eshdn1(u);				u[1] += 1;				}			if( u[NI-1] != 0 )				break;			if( eone[NE-1] <= u[1] )				break;			emovz( u, w );			expon -= 1;			}		emovo( w, y, ldp );		}	k = -MAXP;	p = &emtens[0][0];	r = &etens[0][0];	emov( y, w );	emov( eone, t );	while( ecmp( eone, w ) > 0 )		{		if( ecmp( p, w ) >= 0 )			{			emul( r, w, w, ldp );			emul( r, t, t, ldp );			expon += k;			}		k /= 2;		if( k == 0 )			break;		p += NE;		r += NE;		}	ediv( t, eone, t, ldp );	}isone:/* Find the first (leading) digit. */emovi( t, w );emovz( w, t );emovi( y, w );emovz( w, y );eiremain( t, y, ldp );digit = equot[NI-1];while( (digit == 0) && (ecmp(y,ezero) != 0) )	{	eshup1( y );	emovz( y, u );	eshup1( u );	eshup1( u );	eaddm( u, y );	eiremain( t, y, ldp );	digit = equot[NI-1];	expon -= 1;	}s = string;if( sign )	*s++ = '-';else	*s++ = ' ';/* Examine number of digits requested by caller. */if( outformat == 3 )        ndigs += expon;/*else if( ndigs < 0 )        ndigs = 0;*/if( ndigs > NDEC )	ndigs = NDEC;if( digit == 10 )	{	*s++ = '1';	*s++ = '.';	if( ndigs > 0 )		{		*s++ = '0';		ndigs -= 1;		}	expon += 1;	if( ndigs < 0 )	        {	        ss = s;	        goto doexp;	        }	}else	{	*s++ = (char )digit + '0';	*s++ = '.';	}/* Generate digits after the decimal point. */for( k=0; k<=ndigs; k++ )	{/* multiply current number by 10, without normalizing */	eshup1( y );	emovz( y, u );	eshup1( u );	eshup1( u );	eaddm( u, y );	eiremain( t, y, ldp );	*s++ = (char )equot[NI-1] + '0';	}digit = equot[NI-1];--s;ss = s;/* round off the ASCII string */if( digit > 4 )	{/* Test for critical rounding case in ASCII output. */	if( digit == 5 )		{		emovo( y, t, ldp );		if( ecmp(t,ezero) != 0 )			goto roun;	/* round to nearest */		if( (*(s-1) & 1) == 0 )			goto doexp;	/* round to even */		}/* Round up and propagate carry-outs */roun:	--s;	k = *s & 0x7f;/* Carry out to most significant digit? */	if( ndigs < 0 )		{	        /* This will print like "1E-6". */		*s = '1';		expon += 1;		goto doexp;		}	else if( k == '.' )		{		--s;		k = *s;		k += 1;		*s = (char )k;/* Most significant digit carries to 10? */		if( k > '9' )			{			expon += 1;			*s = '1';			}		goto doexp;		}/* Round up and carry out from less significant digits */	k += 1;	*s = (char )k;	if( k > '9' )		{		*s = '0';		goto roun;		}	}doexp:#ifdef __GO32__if( expon >= 0 )	sprintf( ss, "e+%02d", expon );else	sprintf( ss, "e-%02d", -expon );#else	sprintf( ss, "E%d", expon );#endifbxit:ldp->rndprc = rndsav;ldp->outexpon =  expon;}/*;								ASCTOQ;		ASCTOQ.MAC		LATEST REV: 11 JAN 84;					SLM, 3 JAN 78;;	Convert ASCII string to quadruple precision floating point;;		Numeric input is free field decimal number;		with max of 15 digits with or without ;		decimal point entered as ASCII from teletype.;	Entering E after the number followed by a second;	number causes the second number to be interpreted;	as a power of 10 to be multiplied by the first number;	(i.e., "scientific" notation).;;	Usage:;		asctoq( string, q );*/long double _strtold (char *s, char **se){  long double x;  LDPARMS rnd;  LDPARMS *ldp = &rnd;  int lenldstr;  rnd.rlast = -1;  rnd.rndprc = NBITS;  lenldstr = asctoeg( s, (unsigned short *)&x, LDBL_MANT_DIG, ldp );  if (se)    *se = s + lenldstr;  return x;}#define REASONABLE_LEN 200static intasctoeg(char *ss, short unsigned int *y, int oprec, LDPARMS *ldp){unsigned short yy[NI], xt[NI], tt[NI];int esign, decflg, sgnflg, nexp, exp, prec, lost;int k, trail, c, rndsav;long lexp;unsigned short nsign, *p;char *sp, *s, *lstr;int lenldstr;int mflag = 0;char tmpstr[REASONABLE_LEN];/* Copy the input string. */c = strlen (ss) + 2;if (c <= REASONABLE_LEN)  lstr = tmpstr;else  {    lstr = (char *) calloc (c, 1);    mflag = 1;  }s = ss;lenldstr = 0;while( *s == ' ' ) /* skip leading spaces */  {    ++s;    ++lenldstr;  }sp = lstr;for( k=0; k<c; k++ )	{	if( (*sp++ = *s++) == '\0' )		break;	}*sp = '\0';s = lstr;rndsav = ldp->rndprc;ldp->rndprc = NBITS; /* Set to full precision */lost = 0;nsign = 0;decflg = 0;sgnflg = 0;nexp = 0;exp = 0;prec = 0;ecleaz( yy );trail = 0;nxtcom:k = *s - '0';if( (k >= 0) && (k <= 9) )	{/* Ignore leading zeros */	if( (prec == 0) && (decflg == 0) && (k == 0) )		goto donchr;/* Identify and strip trailing zeros after the decimal point. */	if( (trail == 0) && (decflg != 0) )		{		sp = s;		while( (*sp >= '0') && (*sp <= '9') )			++sp;/* Check for syntax error */		c = *sp & 0x7f;		if( (c != 'e') && (c != 'E') && (c != '\0')			&& (c != '\n') && (c != '\r') && (c != ' ')			&& (c != ',') )			goto error;		--sp;		while( *sp == '0' )			*sp-- = 'z';		trail = 1;		if( *s == 'z' )			goto donchr;		}/* If enough digits were given to more than fill up the yy register, * continuing until overflow into the high guard word yy[2] * guarantees that there will be a roundoff bit at the top * of the low guard word after normalization. */	if( yy[2] == 0 )		{		if( decflg )			nexp += 1; /* count digits after decimal point */		eshup1( yy );	/* multiply current number by 10 */		emovz( yy, xt );		eshup1( xt );		eshup1( xt );		eaddm( xt, yy );		ecleaz( xt );		xt[NI-2] = (unsigned short )k;		eaddm( xt, yy );		}	else		{		/* Mark any lost non-zero digit.  */		lost |= k;		/* Count lost digits before the decimal point.  */		if (decflg == 0)		        nexp -= 1;		}	prec += 1;	goto donchr;	}switch( *s )	{	case 'z':		break;	case 'E':	case 'e':		goto expnt;	case '.':	/* decimal point */		if( decflg )			goto error;		++decflg;		break;	case '-':		nsign = 0xffff;		if( sgnflg )			goto error;		++sgnflg;		break;	case '+':		if( sgnflg )			goto error;		++sgnflg;		break;	case ',':	case ' ':	case '\0':	case '\n':	case '\r':		goto daldone;	case 'i':	case 'I':		goto infinite;	default:	error:#ifdef NANS		enan( yy, NI*16 );#else		mtherr( "asctoe", DOMAIN );		ecleaz(yy);#endif		goto aexit;	}donchr:++s;goto nxtcom;/* Exponent interpretation */expnt:esign = 1;exp = 0;++s;/* check for + or - */if( *s == '-' )	{	esign = -1;	++s;	}if( *s == '+' )	++s;while( (*s >= '0') && (*s <= '9') )	{	exp *= 10;	exp += *s++ - '0';	if (exp > 4977)		{		if (esign < 0)			goto zero;		else			goto infinite;		}	}if( esign < 0 )	exp = -exp;if( exp > 4932 )	{infinite:	ecleaz(yy);	yy[E] = 0x7fff;  /* infinity */	goto aexit;	}if( exp < -4977 )	{zero:	ecle

⌨️ 快捷键说明

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