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

📄 doprnt.c

📁 Algorithms for Image Processing and Computer Vision Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
			for (n = fieldsz; n < dprec; n++)
				PUTC('0');

			/* the string or number proper */
			n = size;
			if (fp->_cnt - n >= 0 && (fp->_flag & _IOLBF) == 0) {
				fp->_cnt -= n;
				bcopy(t, (char *)fp->_ptr, n);
				fp->_ptr += n;
			} else
				while (--n >= 0)
					PUTC(*t++);
			/* trailing f.p. zeroes */
			while (--fpprec >= 0)
				PUTC('0');
			/* left-adjusting padding (always blank) */
			if (flags & LADJUST)
				for (n = realsz; n < width; n++)
					PUTC(' ');
			/* finally, adjust cnt */
			cnt += width > realsz ? width : realsz;
			break;
		case '\0':	/* "%?" prints ?, unless ? is NULL */
			return (cnt);
		default:
			PUTC((char)*fmt);
			cnt++;
		}
	}
	/* NOTREACHED */
}

static long double pten[] =
{
    1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L,
    1e512L, 1e1024L, 1e2048L, 1e4096L
};

static long double ptenneg[] =
{
    1e-1L, 1e-2L, 1e-4L, 1e-8L, 1e-16L, 1e-32L, 1e-64L, 1e-128L, 1e-256L,
    1e-512L, 1e-1024L, 1e-2048L, 1e-4096L
};

#define MAXP 4096
#define NP   12
#define P    (4294967296.0L * 4294967296.0L * 2.0L)   /* 2^65 */
static long double INVPREC = P;
static long double PREC = 1.0L/P;
#undef P
/*
 * Defining FAST_LDOUBLE_CONVERSION results in a little bit faster
 * version, which might be less accurate (about 1 bit) for long
 * double. For 'normal' double it doesn't matter.
 */
/* #define FAST_LDOUBLE_CONVERSION */

static int
cvtl(long double number, int prec, int flags, char *signp, u_char fmtch,
     char *startp, char *endp)
{
	register char *p, *t;
	long double fract;
	int dotrim, expcnt, gformat;
	long double integer, tmp;

#ifdef __GO32__
	if ((expcnt = isspeciall(number, startp)))
		return(expcnt);
#endif

	dotrim = expcnt = gformat = 0;
	/* fract = modfl(number, &integer); */
	integer = number;

	/* get an extra slot for rounding. */
	t = ++startp;

	p = endp - 1;
	if (integer) {
		int i, lp=NP, pt=MAXP;
#ifndef FAST_LDOUBLE_CONVERSION
		long double oint = integer, dd=1.0L;
#endif
		if (integer > INVPREC) {
			integer *= PREC;
			while(lp >= 0) {
				if (integer >= pten[lp]) {
					expcnt += pt;
					integer *= ptenneg[lp];
#ifndef FAST_LDOUBLE_CONVERSION
					dd *= pten[lp];
#endif
				}
				pt >>= 1;
				lp--;
			}
#ifndef FAST_LDOUBLE_CONVERSION
			integer = oint/dd;
#else
			integer *= INVPREC;
#endif
		}
		/*
		 * Do we really need this ?
		 */
		for (i = 0; i < expcnt; i++)
		    *p-- = '0';
	}
	number = integer;
	fract = modfl(number, &integer);
	/*
	 * get integer portion of number; put into the end of the buffer; the
	 * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
	 */
	for (; integer; ++expcnt) {
		tmp = modfl(integer * 0.1L , &integer);
		*p-- = tochar((int)((tmp + .01L) * 10));
	}
	switch(fmtch) {
	case 'f':
		/* reverse integer into beginning of buffer */
		if (expcnt)
			for (; ++p < endp; *t++ = *p);
		else
			*t++ = '0';
		/*
		 * if precision required or alternate flag set, add in a
		 * decimal point.
		 */
		if (prec || flags&ALT)
			*t++ = decimal;
		/* if requires more precision and some fraction left */
		if (fract) {
			if (prec)
				do {
					fract = modfl(fract * 10.0L, &tmp);
					*t++ = tochar((int)tmp);
				} while (--prec && fract);
			if (fract)
				startp = roundl(fract, (int *)NULL, startp,
				    t - 1, (char)0, signp);
		}
		for (; prec--; *t++ = '0');
		break;
	case 'e':
	case 'E':
eformat:	if (expcnt) {
			*t++ = *++p;
			if (prec || flags&ALT)
				*t++ = decimal;
			/* if requires more precision and some integer left */
			for (; prec && ++p < endp; --prec)
				*t++ = *p;
			/*
			 * if done precision and more of the integer component,
			 * round using it; adjust fract so we don't re-round
			 * later.
			 */
			if (!prec && ++p < endp) {
				fract = 0;
				startp = roundl((long double)0.0L, &expcnt,
						startp, t - 1, *p, signp);
			}
			/* adjust expcnt for digit in front of decimal */
			--expcnt;
		}
		/* until first fractional digit, decrement exponent */
		else if (fract) {
			int lp=NP, pt=MAXP;
#ifndef FAST_LDOUBLE_CONVERSION
			long double ofract = fract, dd=1.0L;
#endif
			expcnt = -1;
			if (fract < PREC) {
				fract *= INVPREC;
				while(lp >= 0) {
					if (fract <= ptenneg[lp]) {
						expcnt -= pt;
						fract *= pten[lp];
#ifndef FAST_LDOUBLE_CONVERSION
						dd *= pten[lp];
#endif
					}
					pt >>= 1;
					lp--;
				}
#ifndef FAST_LDOUBLE_CONVERSION
				fract = ofract*dd;
#else
				fract *= PREC;
#endif
			}
			/* adjust expcnt for digit in front of decimal */
			for (/* expcnt = -1 */ ;; --expcnt) {
				fract = modfl(fract * 10.0L, &tmp);
				if (tmp)
					break;
			}
			*t++ = tochar((int)tmp);
			if (prec || flags&ALT)
				*t++ = decimal;
		}
		else {
			*t++ = '0';
			if (prec || flags&ALT)
				*t++ = decimal;
		}
		/* if requires more precision and some fraction left */
		if (fract) {
			if (prec)
				do {
					fract = modfl(fract * 10.0L, &tmp);
					*t++ = tochar((int)tmp);
				} while (--prec && fract);
			if (fract)
				startp = roundl(fract, &expcnt, startp,
				    t - 1, (char)0, signp);
		}
		/* if requires more precision */
		for (; prec--; *t++ = '0');

		/* unless alternate flag, trim any g/G format trailing 0's */
		if (gformat && !(flags&ALT)) {
			while (t > startp && *--t == '0');
			if (*t == decimal)
				--t;
			++t;
		}
		t = exponentl(t, expcnt, fmtch);
		break;
	case 'g':
	case 'G':
		/* a precision of 0 is treated as a precision of 1. */
		if (!prec)
			++prec;
		/*
		 * ``The style used depends on the value converted; style e
		 * will be used only if the exponent resulting from the
		 * conversion is less than -4 or greater than the precision.''
		 *	-- ANSI X3J11
		 */
		if (expcnt > prec || (!expcnt && fract && fract < .0001)) {
			/*
			 * g/G format counts "significant digits, not digits of
			 * precision; for the e/E format, this just causes an
			 * off-by-one problem, i.e. g/G considers the digit
			 * before the decimal point significant and e/E doesn't
			 * count it as precision.
			 */
			--prec;
			fmtch -= 2;		/* G->E, g->e */
			gformat = 1;
			goto eformat;
		}
		/*
		 * reverse integer into beginning of buffer,
		 * note, decrement precision
		 */
		if (expcnt)
			for (; ++p < endp; *t++ = *p, --prec);
		else
			*t++ = '0';
		/*
		 * if precision required or alternate flag set, add in a
		 * decimal point.  If no digits yet, add in leading 0.
		 */
		if (prec || flags&ALT) {
			dotrim = 1;
			*t++ = decimal;
		}
		else
			dotrim = 0;
		/* if requires more precision and some fraction left */
		while (prec && fract) {
			fract = modfl(fract * 10.0L, &tmp);
			*t++ = tochar((int)tmp);
			prec--;
		}
		if (fract)
			startp = roundl(fract, (int *)NULL, startp, t - 1,
					(char)0, signp);
		/* alternate format, adds 0's for precision, else trim 0's */
		if (flags&ALT)
			for (; prec--; *t++ = '0');
		else if (dotrim) {
			while (t > startp && *--t == '0');
			if (*t != decimal)
				++t;
		}
	}
	return(t - startp);
}

static char *
roundl(long double fract, int *exp, char *start, char *end, char ch,
       char *signp)
{
	long double tmp;

	if (fract)
	{
		if (fract == 0.5L)
		{
		    char *e = end;
		    if (*e == '.')
			e--;
		    if (*e == '0' || *e == '2' || *e == '4'
			|| *e == '6' || *e == '8')
		    {
			tmp = 3.0;
			goto start;
		    }
		}
		(void)modfl(fract * 10.0L, &tmp);
	}
	else
		tmp = todigit(ch);
start:
	if (tmp > 4)
		for (;; --end) {
			if (*end == decimal)
				--end;
			if (++*end <= '9')
				break;
			*end = '0';
			if (end == start) {
				if (exp) {	/* e/E; increment exponent */
					*end = '1';
					++*exp;
				}
				else {		/* f; add extra digit */
					*--end = '1';
					--start;
				}
				break;
			}
		}
	/* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
	else if (*signp == '-')
		for (;; --end) {
			if (*end == decimal)
				--end;
			if (*end != '0')
				break;
			if (end == start)
				*signp = 0;
		}
	return(start);
}

static char *
exponentl(char *p, int exp, u_char fmtch)
{
	register char *t;
	char expbuf[MAXEXPLD];

	*p++ = fmtch;
	if (exp < 0) {
		exp = -exp;
		*p++ = '-';
	}
	else
		*p++ = '+';
	t = expbuf + MAXEXPLD;
	if (exp > 9) {
		do {
			*--t = tochar(exp % 10);
		} while ((exp /= 10) > 9);
		*--t = tochar(exp);
		for (; t < expbuf + MAXEXPLD; *p++ = *t++);
	}
	else {
		*p++ = '0';
		*p++ = tochar(exp);
	}
	return(p);
}

#ifdef hp300
isspecial(d, bufp, signp)
	double d;
	char *bufp, *signp;
{
	register struct IEEEdp {
		unsigned sign:1;
		unsigned exp:11;
		unsigned manh:20;
		unsigned manl:32;
	} *ip = (struct IEEEdp *)&d;

	if (ip->exp != 0x7ff)
		return(0);
	if (ip->manh || ip->manl)
		(void)strcpy(bufp, "NaN");
	else
		(void)strcpy(bufp, "Inf");
	return(3);
}
#endif

#ifdef __GO32__
static int
isspeciall(long double d, char *bufp)
{
	register struct IEEExp {
        	unsigned manl:32;
		unsigned manh:32;
		unsigned exp:15;
        	unsigned sign:1;
	} *ip = (struct IEEExp *)&d;

	if (ip->exp != 0x7fff)
		return(0);
	if ((ip->manh & 0x7fffffff) || ip->manl)
    	{
		strcpy(bufp, "NaN");
        	nan = 1; /* kludge: we don't need the sign,  it's not nice
		            but it should work */
    	}
	else
		(void)strcpy(bufp, "Inf");
    	return(3);
}
#endif

⌨️ 快捷键说明

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