Exemplo n.º 1
0
int
ar_ifdiv32 (AR_IEEE_32 *x,
			const AR_IEEE_32 *a,
			const AR_IEEE_32 *b,
			int roundmode) {

	int i, s;
	int res = AR_STAT_OK;
	unsigned long x_lbits, y_lbits, z_lbits, rbits, carry;
	signed int x_expo;
	AR_IEEE_32 y, y2, z, z2;

	/* If either a or b is a NaN, it's the result. */
	if (IS_IEEE32_NaN(a)) {
		*x = *a;
		return res | AR_STAT_UNDEFINED;
	}
	if (IS_IEEE32_NaN(b)) {
		*x = *b;
		return res | AR_STAT_UNDEFINED;
	}

	s = a->sign ^ b->sign;
	/* Test for infinities and zeros */
	if (b->expo > AR_IEEE32_MAX_EXPO)
		if (a->expo > AR_IEEE32_MAX_EXPO) {
			/* infinity / infinity = quiet NaN */
			QNaNIEEE32 (x);
			return res | AR_STAT_UNDEFINED;
		} else {
			/* anything / infinity = zero */
			if (s)
				res |= AR_STAT_NEGATIVE;
			ZEROIEEE32 (*x);
			x->sign = s;
			return res | AR_STAT_UNDERFLOW | AR_STAT_ZERO;
		}
	if (a->expo > AR_IEEE32_MAX_EXPO) {
		/* infinity / anything = infinity */
		if (s)
			res |= AR_STAT_NEGATIVE;
		*x = *a;
		x->sign = s;
		return res | AR_STAT_OVERFLOW;
	}
	if (b->expo == 0 && !IS_IEEE32_NZ_COEFF(b)) {
		if (a->expo == 0 && !IS_IEEE32_NZ_COEFF(a)) {
			/* zero/zero = quiet NaN */
			QNaNIEEE32 (x);
			return res | AR_STAT_UNDEFINED;
		} else {
			/* anything / zero = infinity */
			if (s)
				res |= AR_STAT_NEGATIVE;
			ZEROIEEE32 (*x);
			x->sign = s;
			x->expo = AR_IEEE32_MAX_EXPO + 1;
			return res | AR_STAT_OVERFLOW;
		}
	}

	/* Test for denorms (they have zero exponents) to determine the
	 * values of the implicit normalization bits; make them explicit.
	 */
	if (ar_state_register.ar_denorms_trap &&
		((!a->expo && IS_IEEE32_NZ_COEFF(a)) ||
		 (!b->expo && IS_IEEE32_NZ_COEFF(b)))) {
		/* operand is a denorm and denorms cause a trap */
		x->expo = AR_IEEE32_MAX_EXPO + 1;
		return res | AR_STAT_UNDEFINED;
	}

	y = *a;
	y_lbits = !!a->expo;
	ZEROIEEE32 (y2);
	z = *b;
	z_lbits = !!b->expo;
	ZEROIEEE32 (z2);
	x_lbits = 0;
	x_expo = a->expo - b->expo + !a->expo - !b->expo + AR_IEEE32_EXPO_BIAS;
	ZEROIEEE32 (*x);
	x->sign = s;
	rbits = 0;

	/* Handle division by a denormalized value */
	if (!b->expo) {
		while (!z_lbits) {
			z_lbits = z.coeff0 >> (AR_IEEE32_C0_BITS - 1);
			SHLEFTIEEE32 (z);
			x_expo++;
		}
	}

	if (x_expo <= 0)
		x_expo--;

	/* Divide by repeated subtraction */
	for (i = 0; i < AR_IEEE32_COEFF_BITS + AR_IEEE32_ROUND_BITS + 1; i++) {

		x_lbits = x->coeff0 >> (AR_IEEE32_C0_BITS - 1);
		SHLEFTIEEE32 (*x);
		x->coeff1 |= rbits >> (AR_IEEE32_ROUND_BITS - 1);
		rbits = (rbits << 1) & MASKR (AR_IEEE32_ROUND_BITS);

		/* If scaled denominator <= numerator, subtract */
		if (z_lbits < y_lbits ||
			z_lbits == y_lbits &&
			(z.coeff0 < y.coeff0 ||
			 z.coeff0 == y.coeff0 &&
			 (z.coeff1 < y.coeff1 ||
			  z.coeff1 == y.coeff1 &&
			  (z2.coeff0 < y2.coeff0 ||
			   z2.coeff0 == y2.coeff0 &&
			   z2.coeff1 <= y2.coeff1)))) {

			y2.coeff1 = carry = y2.coeff1 + 1 +
					(z2.coeff1 ^
					 MASKR (AR_IEEE32_C1_BITS));
			carry >>= AR_IEEE32_C1_BITS;
			y2.coeff0 = carry += y2.coeff0 +
					(z2.coeff0 ^
					 MASKR (AR_IEEE32_C0_BITS));
			carry >>= AR_IEEE32_C0_BITS;
			y.coeff1 = carry += y.coeff1 +
					(z.coeff1 ^
					 MASKR (AR_IEEE32_C1_BITS));
			carry >>= AR_IEEE32_C1_BITS;
			y.coeff0 = carry += y.coeff0 +
					(z.coeff0 ^
					 MASKR (AR_IEEE32_C0_BITS));
			carry >>= AR_IEEE32_C0_BITS;
			y_lbits = (y_lbits + carry + (z_lbits ^ 1)) & 1;

			rbits |= 1;
		}

		SHRIGHTIEEE32_2 (z, z2);
		z.coeff0 |= z_lbits << (AR_IEEE32_C0_BITS - 1);
		z_lbits = 0;
	}
Exemplo n.º 2
0
int
ar_ifmul32 (AR_IEEE_32 *x,
			const AR_IEEE_32 *a,
			const AR_IEEE_32 *b,
			int roundmode)
{

	int i, res = AR_STAT_OK;
	unsigned long x_lbits, z_lbits, rbits, carry;
	signed int x_expo;
	AR_IEEE_32 x2, y, y2, z;

	/* If either a or b is a NaN, it's the result. */
	if (IS_IEEE32_NaN(a)) {
		*x = *a;
		return res | AR_STAT_UNDEFINED;
	}
	if (IS_IEEE32_NaN(b)) {
		*x = *b;
		return res | AR_STAT_UNDEFINED;
	}

	/* Test for infinities */
	if (b->expo > AR_IEEE32_MAX_EXPO)
		if (a->expo == 0 && !IS_IEEE32_NZ_COEFF(a)){
			/* zero * inf = quiet NaN */
			QNaNIEEE32 (x);
			return res | AR_STAT_UNDEFINED;
		} else {
			/* anything * infinity = infinity */
			if (i = a->sign ^ b->sign)
				res |= AR_STAT_NEGATIVE;
			*x = *b;
			x->sign = i;
			return res | AR_STAT_OVERFLOW;
		}
	if (a->expo > AR_IEEE32_MAX_EXPO)
		if (b->expo == 0 && !IS_IEEE32_NZ_COEFF(b)){
			/* infinity * zero = quiet NaN */
			QNaNIEEE32 (x);
			return res | AR_STAT_UNDEFINED;
		} else {
			/* infinity * anything = infinity */
			if (i = a->sign ^ b->sign)
				res |= AR_STAT_NEGATIVE;
			*x = *a;
			x->sign = i;
			return res | AR_STAT_OVERFLOW;
		}

	/* Test for denorms (they have zero exponents) to determine the
	 * values of the implicit normalization bits; make them explicit.
	 */
	if (ar_state_register.ar_denorms_trap &&
		((!a->expo && IS_IEEE32_NZ_COEFF(a)) ||
		 (!b->expo && IS_IEEE32_NZ_COEFF(b)))) {
		/* operand is a denorm and denorms cause a trap */
		x->expo = AR_IEEE32_MAX_EXPO + 1;
		return res | AR_STAT_UNDEFINED;
	}
	ZEROIEEE32 (y);
	y.coeff1 = !!a->expo;
	y2 = *a;
	z = *b;
	z_lbits = !!b->expo;
	x_expo = a->expo + b->expo + !a->expo + !b->expo - AR_IEEE32_EXPO_BIAS;
	if (x_expo <= 0)
		x_expo--;
	i = a->sign ^ b->sign;

	/* Sum the pyramid */
	if (z.coeff1 & 1) {
		x2 = *a;
		*x = y;
	}
	else {
		ZEROIEEE32 (*x);
		ZEROIEEE32 (x2);
	}
	x->sign = i;
	x_lbits = z_lbits & y.coeff1;
	SHLEFTIEEE32_2 (y, y2);
	SHRIGHTIEEE32 (z);
	z.coeff0 |= z_lbits << (AR_IEEE32_C0_BITS - 1);
	for (i = 1; i < AR_IEEE32_COEFF_BITS + 1; i++) {

		if (z.coeff1 & 1) {
			carry = 0;
			ADDIEEE32 (x2, carry, x2, y2);
			ADDIEEE32 (*x, carry, *x, y);
			x_lbits += carry;
		}

		SHLEFTIEEE32_2 (y, y2);
		SHRIGHTIEEE32 (z);
	}

	/* Extract rounding bits */
	rbits = x2.coeff0 >> (AR_IEEE32_C0_BITS - AR_IEEE32_ROUND_BITS);
	if (x2.coeff0 & MASKR (AR_IEEE32_C0_BITS - AR_IEEE32_ROUND_BITS) |
		x2.coeff1)
		rbits |= 1; /* sticky bit */

	/* Normalize and round */
	return ar_i32norm (x_expo, x_lbits, rbits, x, roundmode);
}