Exemple #1
0
void fex_merge_flags(const fenv_t *p)
{
	unsigned long	fsr;

	__fenv_getfsr(&fsr);
	__fenv_set_ex(fsr, __fenv_get_ex(fsr) | __fenv_get_ex(p->__fsr));
	__fenv_setfsr(&fsr);
	if (fex_get_log())
		__fex_update_te();
}
Exemple #2
0
/*
 * fmal for SPARC: 128-bit quad precision, big-endian
 */
long double
__fmal(long double x, long double y, long double z) {
	union {
		unsigned i[4];
		long double q;
	} xx, yy, zz;
	union {
		unsigned i[2];
		double d;
	} u;
	double dx[5], dy[5], dxy[9], c, s;
	unsigned xy0, xy1, xy2, xy3, xy4, xy5, xy6, xy7;
	unsigned z0, z1, z2, z3, z4, z5, z6, z7;
	unsigned fsr, rm, sticky;
	int hx, hy, hz, ex, ey, ez, exy, sxy, sz, e, ibit;
	int cx, cy, cz;
	volatile double	dummy;

	/* extract the high order words of the arguments */
	xx.q = x;
	yy.q = y;
	zz.q = z;
	hx = xx.i[0] & ~0x80000000;
	hy = yy.i[0] & ~0x80000000;
	hz = zz.i[0] & ~0x80000000;

	/*
	 * distinguish zero, finite nonzero, infinite, and quiet nan
	 * arguments; raise invalid and return for signaling nans
	 */
	if (hx >= 0x7fff0000) {
		if ((hx & 0xffff) | xx.i[1] | xx.i[2] | xx.i[3]) {
			if (!(hx & 0x8000)) {
				/* signaling nan, raise invalid */
				dummy = snan;
				dummy += snan;
				xx.i[0] |= 0x8000;
				return (xx.q);
			}
			cx = 3;	/* quiet nan */
		} else
			cx = 2;	/* inf */
	} else if (hx == 0) {
		cx = (xx.i[1] | xx.i[2] | xx.i[3]) ? 1 : 0;
				/* subnormal or zero */
	} else
		cx = 1;		/* finite nonzero */

	if (hy >= 0x7fff0000) {
		if ((hy & 0xffff) | yy.i[1] | yy.i[2] | yy.i[3]) {
			if (!(hy & 0x8000)) {
				dummy = snan;
				dummy += snan;
				yy.i[0] |= 0x8000;
				return (yy.q);
			}
			cy = 3;
		} else
			cy = 2;
	} else if (hy == 0) {
		cy = (yy.i[1] | yy.i[2] | yy.i[3]) ? 1 : 0;
	} else
		cy = 1;

	if (hz >= 0x7fff0000) {
		if ((hz & 0xffff) | zz.i[1] | zz.i[2] | zz.i[3]) {
			if (!(hz & 0x8000)) {
				dummy = snan;
				dummy += snan;
				zz.i[0] |= 0x8000;
				return (zz.q);
			}
			cz = 3;
		} else
			cz = 2;
	} else if (hz == 0) {
		cz = (zz.i[1] | zz.i[2] | zz.i[3]) ? 1 : 0;
	} else
		cz = 1;

	/* get the fsr and clear current exceptions */
	__fenv_getfsr(&fsr);
	fsr &= ~FSR_CEXC;

	/* handle all other zero, inf, and nan cases */
	if (cx != 1 || cy != 1 || cz != 1) {
		/* if x or y is a quiet nan, return it */
		if (cx == 3) {
			__fenv_setfsr(&fsr);
			return (x);
		}
		if (cy == 3) {
			__fenv_setfsr(&fsr);
			return (y);
		}

		/* if x*y is 0*inf, raise invalid and return the default nan */
		if ((cx == 0 && cy == 2) || (cx == 2 && cy == 0)) {
			dummy = zero;
			dummy *= inf;
			zz.i[0] = 0x7fffffff;
			zz.i[1] = zz.i[2] = zz.i[3] = 0xffffffff;
			return (zz.q);
		}

		/* if z is a quiet nan, return it */
		if (cz == 3) {
			__fenv_setfsr(&fsr);
			return (z);
		}

		/*
		 * now none of x, y, or z is nan; handle cases where x or y
		 * is inf
		 */
		if (cx == 2 || cy == 2) {
			/*
			 * if z is also inf, either we have inf-inf or
			 * the result is the same as z depending on signs
			 */
			if (cz == 2) {
				if ((int) ((xx.i[0] ^ yy.i[0]) ^ zz.i[0]) < 0) {
					dummy = inf;
					dummy -= inf;
					zz.i[0] = 0x7fffffff;
					zz.i[1] = zz.i[2] = zz.i[3] =
						0xffffffff;
					return (zz.q);
				}
				__fenv_setfsr(&fsr);
				return (z);
			}

			/* otherwise the result is inf with appropriate sign */
			zz.i[0] = ((xx.i[0] ^ yy.i[0]) & 0x80000000) |
				0x7fff0000;
			zz.i[1] = zz.i[2] = zz.i[3] = 0;
			__fenv_setfsr(&fsr);
			return (zz.q);
		}

		/* if z is inf, return it */
		if (cz == 2) {
			__fenv_setfsr(&fsr);
			return (z);
		}

		/*
		 * now x, y, and z are all finite; handle cases where x or y
		 * is zero
		 */
		if (cx == 0 || cy == 0) {
			/* either we have 0-0 or the result is the same as z */
			if (cz == 0 && (int) ((xx.i[0] ^ yy.i[0]) ^ zz.i[0]) <
				0) {
				zz.i[0] = (fsr >> 30) == FSR_RM ? 0x80000000 :
					0;
				__fenv_setfsr(&fsr);
				return (zz.q);
			}
			__fenv_setfsr(&fsr);
			return (z);
		}

		/* if we get here, x and y are nonzero finite, z must be zero */
		return (x * y);
	}
Exemple #3
0
int fesetenv(const fenv_t *p)
{
	__fenv_setfsr(&p->__fsr);
	fex_setexcepthandler(&p->__handlers, FEX_ALL);
	return 0;
}