OpenSolaris_b135/lib/libbc/libc/gen/common/_sprintf_sup.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 1988 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include "base_conversion.h"

/*
 * Fundamental utilities of base conversion required for sprintf - but too
 * complex or too seldom used to be worth assembly language coding.
 */

/* p = x * y + c ; return (p/10000 << 16 | p%10000) */
unsigned long
_prodc_b10000(_BIG_FLOAT_DIGIT x, _BIG_FLOAT_DIGIT y, unsigned long c)
{
	unsigned long   p = x * (unsigned long) y + c;

	return ((p / 10000) << 16) | (p % 10000);
}

/* p = x * y ; return p */
unsigned long
_prod_b65536(_BIG_FLOAT_DIGIT x, _BIG_FLOAT_DIGIT y)	
{
	return (x * (unsigned long)y);
}

/* p = x * y ; return (p/10000 << 16 | p%10000) */
unsigned long
_prod_b10000(_BIG_FLOAT_DIGIT x, _BIG_FLOAT_DIGIT y)	
{
	unsigned long   p = x * (unsigned long) y;

	return ((p / 10000) << 16) | (p % 10000);
}

/* p = x << n + c ; return (p/10000 << 16 | p%10000) */
unsigned long
_lshift_b10000(_BIG_FLOAT_DIGIT x, short unsigned n, long unsigned c)	
{
	unsigned long   p = (((unsigned long) x) << n) + c;

	return ((p / 10000) << 16) | (p % 10000);
}

/* p = x * 10000 + c ; return p */
unsigned long
_prod_10000_b65536(_BIG_FLOAT_DIGIT x, long unsigned c)
{
	return (x * (unsigned long) 10000 + c);
}

/* p = x << 16 + c ; return (p/10000 << 16 | p%10000) */
unsigned long
_prod_65536_b10000(_BIG_FLOAT_DIGIT x, long unsigned c)	
{
	unsigned long   p = (((unsigned long) x) << 16) + c;

	return ((p / 10000) << 16) | (p % 10000);
}

/* p = c ; return (p/10000 << 16 | p%10000) */
unsigned long
_carry_out_b10000(unsigned long c)
{
	return ((c / 10000) << 16) | (c % 10000);
}

void
_left_shift_base_ten(_big_float *pbf, short unsigned multiplier)
{
	/*
	 * Multiply a base-10**4 significand by 2<<multiplier.  Extend length
	 * as necessary to accommodate carries.
	 */

	short unsigned  length = pbf->blength;
	int             j;
	unsigned long   carry;
	long            p;

	carry = 0;
	for (j = 0; j < length; j++) {
		p = _lshift_b10000((_BIG_FLOAT_DIGIT) pbf->bsignificand[j], multiplier, carry);
		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
		carry = p >> 16;
	}
	while (carry != 0) {
		p = _carry_out_b10000(carry);
		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
		carry = p >> 16;
	}
	pbf->blength = j;
}

void
_left_shift_base_two(_big_float *pbf, short unsigned multiplier)
{
	/*
	 * Multiply a base-2**16 significand by 2<<multiplier.  Extend length
	 * as necessary to accommodate carries.
	 */

	short unsigned  length = pbf->blength;
	long unsigned   p;
	int             j;
	unsigned long   carry;

	carry = 0;
	for (j = 0; j < length; j++) {
		p = _lshift_b65536(pbf->bsignificand[j], multiplier, carry);
		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
		carry = p >> 16;
	}
	if (carry != 0) {
		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (_carry_out_b65536(carry) & 0xffff);
	}
	pbf->blength = j;
}

void
_right_shift_base_two(_big_float *pbf, short unsigned multiplier,
    _BIG_FLOAT_DIGIT *sticky)
{
	/* *pb = *pb / 2**multiplier	to normalize.	15 <= multiplier <= 1 */
	/* Any bits shifted out got to *sticky. */

	long unsigned   p;
	int             j;
	unsigned long   carry;

	carry = 0;
	for (j = pbf->blength - 1; j >= 0; j--) {
		p = _rshift_b65536(pbf->bsignificand[j], multiplier, carry);
		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p >> 16);
		carry = p & 0xffff;
	}
	*sticky = (_BIG_FLOAT_DIGIT) carry;
}

void
_multiply_base_ten(_big_float *pbf, _BIG_FLOAT_DIGIT multiplier)
{
	/*
	 * Multiply a base-10**4 significand by multiplier.  Extend length as
	 * necessary to accommodate carries.
	 */

	int             j;
	unsigned long   carry;
	long            p;

	carry = 0;
	for (j = 0; j < pbf->blength; j++) {
		p = _prodc_b10000((_BIG_FLOAT_DIGIT) pbf->bsignificand[j], multiplier, carry);
		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
		carry = p >> 16;
	}
	while (carry != 0) {
		p = _carry_out_b10000(carry);
		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
		carry = p >> 16;
	}
	pbf->blength = j;
}

void
_multiply_base_two(_big_float *pbf, _BIG_FLOAT_DIGIT multiplier,
    long unsigned carry)
{
	/*
	 * Multiply a base-2**16 significand by multiplier.  Extend length as
	 * necessary to accommodate carries.
	 */

	short unsigned  length = pbf->blength;
	long unsigned   p;
	int             j;

	for (j = 0; j < length; j++) {
		p = _prodc_b65536(pbf->bsignificand[j], multiplier, carry);
		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
		carry = p >> 16;
	}
	if (carry != 0) {
		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (_carry_out_b65536(carry) & 0xffff);
	}
	pbf->blength = j;
}

void
_multiply_base_ten_by_two(_big_float *pbf, short unsigned multiplier)
{
	/*
	 * Multiply a base-10**4 significand by 2**multiplier.  Extend length
	 * as necessary to accommodate carries.
	 */

	short unsigned  length = pbf->blength;
	int             j;
	long unsigned   carry, p;

	carry = 0;
	for (j = 0; j < length; j++) {
		p = _lshift_b10000(pbf->bsignificand[j], multiplier, carry);
		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
		carry = p >> 16;
	}
	while (carry != 0) {
		p = _carry_out_b10000(carry);
		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
		carry = p >> 16;
	}
	pbf->blength = j;
}

void
_unpacked_to_big_float(unpacked *pu, _big_float *pb, int *pe)
{
	/*
	 * Converts pu into a bigfloat *pb of minimal length; exponent *pe
	 * such that pu = *pb * 2 ** *pe
	 */

	int             iz, it;

	for (iz = (UNPACKED_SIZE - 2); pu->significand[iz] == 0; iz--);	/* Find lsw. */

	for (it = 0; it <= iz; it++) {
		pb->bsignificand[2 * (iz - it)] = pu->significand[it] & 0xffff;
		pb->bsignificand[2 * (iz - it) + 1] = pu->significand[it] >> 16;
	}

	pb->blength = 2 * iz + 2;
	if (pb->bsignificand[0] == 0) {
		for (it = 1; it < pb->blength; it++)
			pb->bsignificand[it - 1] = pb->bsignificand[it];
		pb->blength--;
	}
	*pe = pu->exponent + 1 - 16 * pb->blength;
	pb->bexponent = 0;

#ifdef DEBUG
	printf(" unpacked to big float 2**%d * ", *pe);
	_display_big_float(pb, 2);
#endif
}

void
_mul_65536short(_big_float *pbf, unsigned long carry)
{
	/* *pbf *= 65536 ; += carry ; */

	long unsigned   p;
	int             j;

	for (j = 0; j < pbf->blength; j++) {
		p = _prod_65536_b10000(pbf->bsignificand[j], carry);
		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
		carry = p >> 16;
	}
	while (carry != 0) {
		p = _carry_out_b10000(carry);
		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
		carry = p >> 16;
	}
	pbf->blength = j;
}

void
_big_binary_to_big_decimal(_big_float *pb, _big_float *pd)
{
	/* Convert _big_float from binary form to decimal form. */

	int             i;

	pd->bsignificand[0] = pb->bsignificand[pb->blength - 1] % 10000;
	if (pd->bsignificand[0] == pb->bsignificand[pb->blength - 1]) {
		pd->blength = 1;
	} else {
		pd->blength = 2;
		pd->bsignificand[1] = pb->bsignificand[pb->blength - 1] / 10000;
	}
	for (i = pb->blength - 2; i >= 0; i--) {	/* Multiply by 2**16 and
							 * add next significand. */
		_mul_65536short(pd, (unsigned long) pb->bsignificand[i]);
	}
	for (i = 0; i <= (pb->bexponent - 16); i += 16) {	/* Multiply by 2**16 for
								 * each trailing zero. */
		_mul_65536short(pd, (unsigned long) 0);
	}
	if (pb->bexponent > i)
		_left_shift_base_ten(pd, (short unsigned) (pb->bexponent - i));
	pd->bexponent = 0;

#ifdef DEBUG
	printf(" _big_binary_to_big_decimal ");
	_display_big_float(pd, 10);
#endif
}