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

📄 decimal_bin.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#if !defined(lint) && defined(SCCSIDS)static char     sccsid[] = "@(#)decimal_bin.c 1.1 92/07/30 SMI";#endif/* * Copyright (c) 1988 by Sun Microsystems, Inc. *//* Conversion between binary and decimal floating point. */#include "base_conversion.h"voiddecimal_to_binary_integer(ds, ndigs, nzeros, nsig, pb)	char            ds[];	/* Input decimal integer string. */unsigned        ndigs;		/* Input number of explicit digits in ds. */unsigned        nzeros;		/* Input number of implicit trailing zeros. */unsigned        nsig;		/* Input number of significant bits required. */_big_float     *pb;		/* Pointer to big_float to receive result. *//* * Converts a decimal integer string ds with ndigs explicit leading digits * and nzeros implicit trailing zeros to a _big_float **pb, which only * requires nsig significand bits. *//* Inexactness is indicated by pb->bsignificand[0] |= 1. *//* * If the input is too big for a big_float, pb->bexponent is set to 0x7fff. */{	unsigned        nzout;	_big_float      d, *pbout;	d.bsize = _BIG_FLOAT_SIZE;	_integerstring_to_big_decimal(ds, ndigs, nzeros, &nzout, &d);	_big_decimal_to_big_binary(&d, pb);	if (nzout != 0) {		_big_float_times_power(pb, 10, (int) nzout, (int) nsig, &pbout);		switch (pbout) {		case BIG_FLOAT_TIMES_TOOBIG:#ifdef DEBUG			(void) printf(" decimal_to_binary_integer: decimal exponent %d too large for tables ", nzout);#endif			pb->bexponent = 0x7fff;			break;		case BIG_FLOAT_TIMES_NOMEM:			{				char            bcastring[80];				(void) sprintf(bcastring, " decimal exponent %d ", nzout);				_base_conversion_abort(ENOMEM, bcastring);				break;			}		default:#ifdef DEBUG			if (pbout != pb)				(void) printf(" decimal_to_binary_integer: large decimal exponent %d needs heap buffer \n", nzout);			printf(" decimal_to_binary_integer: product ");			_display_big_float(pb, 2);#endif			if (pbout != pb) {	/* We don't really need such						 * a large product; the						 * target can't be more than						 * a quad! */				int             i, allweneed;				allweneed = 2 + (nsig + 2) / 16;				for (i = 0; i < allweneed; i++)					pb->bsignificand[i] = pbout->bsignificand[i + pbout->blength - allweneed];				for (i = 0; (pbout->bsignificand[i] == 0); i++);				if (i < (pbout->blength - allweneed))					pb->bsignificand[0] |= 1;	/* Stick discarded bits. */				pb->blength = allweneed;				pb->bexponent = pbout->bexponent + 16 * (pbout->blength - allweneed);#ifdef DEBUG				printf(" decimal_to_binary_integer: removed %d excess digits from product \n", pbout->blength - allweneed);				_display_big_float(pb, 2);#endif				_free_big_float(pbout);			}			break;		}	}}voiddecimal_to_binary_fraction(ds, ndigs, nzeros, nsig, pb)	char            ds[];	/* Decimal integer string input. */unsigned        ndigs;		/* Number of explicit digits to read. */unsigned        nzeros;		/* Number of implicit leading zeros before				 * digits. */unsigned        nsig;		/* Number of significant bits needed. */_big_float     *pb;		/* Pointer to intended big_float result. *//* * Converts an explicit decimal string *ds[0]..*ds[ndigs-1] preceded by * nzeros implicit leading zeros after the point into a big_float at *pb. If * the input does not fit exactly in a big_float, the least significant bit * of pbout->significand is stuck on. If the input is too big for the base * conversion tables, pb->bexponent is set to 0x7fff. */{	unsigned        twopower, twosig;	int             i, excess;	_big_float      d, *pdout;	d.bsize = _BIG_FLOAT_SIZE;	_fractionstring_to_big_decimal(ds, ndigs, nzeros, &d);	twopower = nsig + 3 + (((nzeros + 1) * (unsigned long) 217706) >> 16);	twosig = 1 + (((nsig + 2) * (unsigned long) 19729) >> 16);#ifdef DEBUG	printf(" decimal_to_binary_fraction sigbits %d twopower %d twosig %d \n",	       nsig, twopower, twosig);#endif	_big_float_times_power(&d, 2, (int) twopower, (int) twosig, &pdout);	switch (pdout) {	case BIG_FLOAT_TIMES_TOOBIG:#ifdef DEBUG		(void) printf(" decimal_to_binary_fraction binary exponent %d too large for tables ", twopower);#endif		pb->bexponent = 0x7fff;		goto ret;	case BIG_FLOAT_TIMES_NOMEM:		{			char            bcastring[80];			(void) sprintf(bcastring, " binary exponent %d ", twopower);			_base_conversion_abort(ENOMEM, bcastring);			break;		}	default:#ifdef DEBUG		if (&d != pdout)			printf(" decimal_to_binary_fraction large binary exponent %d needs heap buffer \n", twopower);		printf(" product ");		_display_big_float(pdout, 10);#endif		break;	}	if (pdout->bexponent <= -4) {		/* Have computed appropriate decimal part; now toss fraction. */		excess = (-pdout->bexponent) / 4;#ifdef DEBUG		printf(" discard %d excess fraction digits \n", 4 * excess);#endif		for (i = 0; (i < excess) && ((pdout)->bsignificand[i] == 0); i++);		if (i < excess)			(pdout)->bsignificand[excess] |= 1;	/* Sticky bit for								 * discarded fraction. */		for (i = excess; i < (pdout)->blength; i++)			(pdout)->bsignificand[i - excess] = (pdout)->bsignificand[i];		(pdout)->blength -= excess;		(pdout)->bexponent += 4 * excess;	}	_big_decimal_to_big_binary(pdout, pb);	if (pdout != &d)		_free_big_float(pdout);	pb->bexponent = -twopower;ret:	return;}voiddecimal_to_unpacked(px, pd, significant_bits)	unpacked       *px;	decimal_record *pd;	unsigned        significant_bits;/* * Converts *pd to *px so that *px can be correctly rounded. significant_bits * tells how many bits will be significant in the final result to avoid * superfluous computation. Inexactness is communicated by sticking on the * lsb of px->significand[UNPACKED_SIZE-1]. Integer buffer overflow is * indicated with a huge positive exponent. */{	int             frac_bits, sigint;	unsigned        length, ndigs, ntz, nlz, ifrac, nfrac;	_big_float      bi, bf, *ptounpacked = &bi;	px->sign = pd->sign;	px->fpclass = pd->fpclass;	if ((px->fpclass != fp_normal) && (px->fpclass != fp_subnormal))		goto ret;	for (length = 0; pd->ds[length] != 0; length++);	if (length == 0) {	/* A zero significand slipped by. */		px->fpclass = fp_zero;		goto ret;	}	/* Length contains the number of explicit digits in string. */	if (pd->exponent >= 0) {/* All integer digits. */		ndigs = length;		ntz = pd->exponent;	/* Trailing zeros. */		ifrac = 0;		nfrac = 0;	/* No fraction digits. */		nlz = 0;	} else if (length <= -pd->exponent) {	/* No integer digits. */		ndigs = 0;		ntz = 0;		ifrac = 0;		nfrac = length;		nlz = -pd->exponent - length;	/* Leading zeros. */	} else {		/* Some integer digits, some fraction digits. */		ndigs = length + pd->exponent;		ntz = 0;		ifrac = ndigs;		nfrac = -pd->exponent;		nlz = 0;		while ((pd->ds[ifrac] == '0') && (nfrac != 0)) {			ifrac++;			nfrac--;			nlz++;		}		/* Remove leading zeros. */	}	if (ndigs != 0) {	/* Convert integer digits. */		bi.bsize = _BIG_FLOAT_SIZE;		decimal_to_binary_integer(pd->ds, ndigs, ntz, significant_bits, &bi);		if (bi.bexponent == 0x7fff) {	/* Too big for buffer. */			px->exponent = 0x7fffffff;			px->significand[0] = 0x80000000;			goto ret;		}		sigint = 16 * (bi.blength + bi.bexponent - 1);		if (sigint < 0)			sigint = 0;	} else {		/* No integer digits. */		bi.blength = 0;		bi.bsignificand[0] = 0;		bi.bexponent = 0;		sigint = 0;	}	frac_bits = significant_bits - sigint + 2;	bf.blength = 0;	if ((nfrac != 0) && (frac_bits > 0)) {	/* Convert fraction digits,						 * even if we only need a						 * round or sticky.  */		bf.bsize = _BIG_FLOAT_SIZE;		decimal_to_binary_fraction(&(pd->ds[ifrac]), nfrac, nlz, (unsigned) frac_bits, &bf);	} else {		/* Only need fraction bits for sticky. */		if (nfrac != 0)			bi.bsignificand[0] |= 1;	/* Stick for fraction. */	}	if (bi.blength == 0) {	/* No integer digits; all fraction. */		if (bf.bexponent == 0x7fff) {	/* Buffer overflowed. */			px->exponent = -0x7fffffff;			px->significand[0] = 0x80000000;			goto ret;		}		ptounpacked = &bf;	/* Exceptional case - all fraction. */		goto punpack;	}	if (bf.blength != 0) {	/* Combine integer and fraction bits. */		int             expdiff = bi.bexponent - (bf.bexponent + 16 * (bf.blength - 1));	/* Exponent difference. */		int             uneeded = 2 + (significant_bits + 2) / 16;	/* Number of big float										 * digits needed. */		int             nmove, leftshift, i, if0;#ifdef DEBUG		printf(" bi+bf exponent diff is %d \n", expdiff);		printf(" need %d big float digits \n", uneeded);		assert(bi.blength != 0);		assert(bf.blength != 0);		assert(bi.bsignificand[bi.blength - 1] != 0);	/* Normalized bi. */		assert(bf.bsignificand[bf.blength - 1] != 0);	/* Normalized bf. */		assert(bi.bexponent >= 0);	/* bi is all integer */		assert(((-bf.bexponent - 16 * (bf.blength - 1)) >= 16) ||		       ((bf.bsignificand[bf.blength - 1] >> (-bf.bexponent - 16 * (bf.blength - 1))) == 0));		/* assert either bf << 1 or bf < 1 */		/*		 * Assert that integer and fraction parts don't overlap by		 * more than one big digit.		 */		assert(expdiff > 0);		assert(uneeded <= (2 * UNPACKED_SIZE));#endif		if (bi.blength >= uneeded) {	/* bi will overflow unpacked,						 * so bf is just a sticky. */			bi.bsignificand[0] |= 1;			goto punpack;		}		leftshift = 16 - (expdiff % 16);		if (leftshift > 0) {	/* shift bf to align with bi. */			expdiff += 16 * bf.blength;			_left_shift_base_two(&bf, (short unsigned) leftshift);			expdiff -= 16 * bf.blength;	/* If bf.blength is							 * longer, adjust							 * expdiff. */		}		expdiff += leftshift;		expdiff /= 16;	/* Remaining expdiff in _BIG_FLOAT_DIGITS. */		expdiff--;#ifdef DEBUG		assert(expdiff >= 0);	/* expdiff is now equal to the size					 * of the hole between bi and bf. */#endif		nmove = uneeded - bi.blength;		/* nmove is the number of words to add to bi. */		if (nmove < 0)			nmove = 0;		if (nmove > (expdiff + bf.blength))			nmove = (expdiff + bf.blength);#ifdef DEBUG		printf(" increase bi by %d words to merge \n", nmove);#endif		if (nmove == 0)			i = -1;		else			for (i = (bi.blength - 1 + nmove); i >= nmove; i--)				bi.bsignificand[i] = bi.bsignificand[i - nmove];		for (; (i >= 0) && (expdiff > 0); i--) {	/* Fill hole with zeros. */			expdiff--;			bi.bsignificand[i] = 0;		}		if0 = i;		for (; i >= 0; i--)			bi.bsignificand[i] = bf.bsignificand[i + bf.blength - 1 - if0];		for (i = (bf.blength - 2 - if0); bf.bsignificand[i] == 0; i--);		/* Find first non-zero. */		if (i >= 0)

⌨️ 快捷键说明

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