Esempio n. 1
0
/**
Cast to 64 bit int (assuming double & long long have same endianness),
convert from sign-magnitude to 2s-complement,
return (magnitude of) difference in ULPs.

The difference between 2 64-bit numbers is a 65-bit number, so only get the
magnitude of the difference. The usual floating point comparisons (<code>a > b</code>, etc)
can be used to find which is bigger.

This currently uses isnan and isinf, if they are not defined they should be
implemented using bitwise comparisons. isnan must not use <code>x != x</code>, or eqivalent.

If no 64bit unsigned int is provided then it becomes very complicated to implement this function.

\param a,b Any 64-bit non-denormalised floating point numbers.

\return The unsigned distance between <code>a</code> and <code>b</code> in 'floating point space'.
 */
uint64_t cbf_ULP64(const double a, const double b)
{
	/*
	Check for NAN or INF, ignore subnormals completely.
	Don't use 'x!=x' to test for NANs, it might be optimised out,
	test for a bit pattern manually if 'isnan' or 'isinf' can't be used.
	*/
	if (isnan64(a) || isinf64(a) || isnan64(b) || isinf64(b)) {
		if (isinf64(a) && isinf64(b) && a==b) return 0;
		return 0xffffffffffffffffl;
	} else {
		const uint64_t signmask = 0x8000000000000000l;

		/* cast numbers so that ia >= ib */
		uint64_t ia = *(int64_t*)(a>b ? &a : &b);
		uint64_t ib = *(int64_t*)(a>b ? &b : &a);

		/* convert to 2's complement form */
		ia = signmask&ia ? signmask^(~ia+1) : ia;
		ib = signmask&ib ? signmask^(~ib+1) : ib;

		/* subtract, knowing that ia >= ib */
		return ia-ib;
	}
}
Esempio n. 2
0
_f_int2
_IEEE_EXPONENT_I2_H(_f_real8 x)
{
	int		i;
	REGISTER_8	s1;

	/* if x is a NaN, return HUGE */
	if (isnan64(x)) 
		return(HUGE_INT2_F90);

	s1.f	= x;

	/* clear sign bit. */
	s1.ui &= ~IEEE_64_SIGN_BIT;

	/* if x is + or minus infinity, return a HUGE */
	if (s1.ui == IEEE_64_INFINITY)
		return(HUGE_INT2_F90);

	/* if x is zero, return -HUGE */
	if (x == 0.0e0)
		return(-HUGE_INT2_F90);

	i	= __ieee_real4i(x);
	return ((_f_int2) i);
}
Esempio n. 3
0
/* _IEEE_EXPONENT_I6_R - IEEE EXPONENT returns the exponent part of the
 *                      64-bit argument in 46-bit integer.
 */
_f_int6
_IEEE_EXPONENT_I6_R(_f_real8 x)
{
	int		i;
	REGISTER_8	s1, s2;

	/* if x is a NaN, return HUGE */
	if (isnan64(x))
		return HUGE_INT6_F90;
	s1.f = x;

	/* clear sign bit */
	s1.ui &= ~IEEE_64_SIGN_BIT;

	/* if x is + or - infinity, return HUGE */
	if (s1.ui == IEEE_64_INFINITY)
		return HUGE_INT6_F90;

	/* if x is zero, return -HUGE */
	if (x == 0.0e0)
		return -HUGE_INT6_F90;

	/* shift exponent bits to right. */
	s1.ui >>= IEEE_64_MANT_BITS;
	if (s1.ui == 0) {

		/* x is a subnormal number (implicit leading bit is zero
		 * and the exponent is zero).  Calculate the exponent
		 * based on normalized x.
	 	 *
		 * get mantissa
		 */
		s2.f = x;
		s2.ui = IEEE_64_MANTISSA & s2.ui;

		/* get leading zeros in mantissa part. */
		i = _leadz8(s2.ui) - IEEE_64_EXPO_BITS;

		/* calculate exponent. */
		s1.i -= (IEEE_64_EXPO_BIAS + i);
	} else {
		/* subtract exponent bias. */
		s1.i -= (IEEE_64_EXPO_BIAS);
	}
	return (_f_int6) s1.i;
}
Esempio n. 4
0
inline static		/* for the inline version of this function. */
#endif
_f_real8
_FRACTION(_f_real8 x)
{
	int             lz;
	REGISTER_8      s1, sign_bit, mantissa, exponent;
	if (x == 0.0)
		return 0.0;
	/* if x is either infinity or a NaN, return a Nan */
	if (x == IEEE_64_INFINITY)
		return	_SGL_NaN;
	if (isnan64(x))
		return	x;
	s1.f = x;

	/* get sign bit. */
	sign_bit.ui = IEEE_64_SIGN_BIT & s1.ui;

	/* get mantissa. */
	mantissa.ui = IEEE_64_MANTISSA & s1.ui;

	/* get exponent. */
	exponent.ui = IEEE_64_EXPONENT & s1.ui;
	if (exponent.ui == LL_CONST(0x0)) {

		/* 1. number is subnormal.  normalize mantissa.
		 * Get leading zeros of mantissa.
		 */
		lz = _leadz8(mantissa.ui) - IEEE_64_EXPO_BITS;

		/* 2. normalize by shifting out all leading zeros
		 *    and first 1 bit.
		 */
		mantissa.ui = (mantissa.ui << lz) & IEEE_64_MANTISSA;
	}

	/* position exponent bias less the implicit bit. */
	exponent.ui = IEEE_64_EXPO_BIAS - 1;
	exponent.ui = exponent.ui << IEEE_64_MANT_BITS;

	/* extract fraction. */
	s1.ui = exponent.ui | mantissa.ui | sign_bit.ui;
	return s1.f;
}
_f_real8
_IEEE_BINARY_SCALE_I8(_f_real8 orig_number, _f_int8 orig_scale_factor)
{
	int	lz, lzm, shift;
	REGISTER_8	number, scale_factor, expon, exponent,
			orig_mantissa, mantissa, sign_bit;

	/* if x is a NaN, return a Nan */
	if (isnan64(orig_number))
		return orig_number;
	number.f =	orig_number;

	/* extract sign bit. */
	sign_bit.ui =	IEEE_64_SIGN_BIT & number.ui;

	/* extract exponent. */
	exponent.ui =	IEEE_64_EXPONENT & number.ui;

	/* extract mantissa. */
	orig_mantissa.ui = IEEE_64_MANTISSA & number.ui;

	/* if x is + or -infinity, return same infinity */
	number.ui &= ~IEEE_64_SIGN_BIT;
	if (number.ui == IEEE_64_INFINITY)
		return orig_number;

	/* if x is zero, return zero. */
	if (orig_number == 0)
		return orig_number;

	scale_factor.i =	orig_scale_factor;

	/* check for unnormalized number */
	if (exponent.ui == 0) {

		/* Denormmal.  Get leading zeros in original mantissa */
		lz =	_leadz8(orig_mantissa.ui);

		if (scale_factor.i > 0) {

			/* Scale number by a positive power of 2.  The
			 * result may need to be normalized.  Get
			 * leading zeros in mantissa = lzm.
			 */
			lzm = lz - IEEE_64_EXPO_BITS - 1;

			/* Any leading zeros in mantissa? */
			if (lzm > 0) {

				/* check if number of leading zeros in
				 * mantissa allows scaling by shifting.
				 */
				if (scale_factor.i <= lzm) {

					/* Enough lead zeros to shift.
					 * Exponent is unaffected.
					 */
					shift = scale_factor.i;
					expon.i = 0;
				} else {

					/* Scale by shifting what we can
					 * and adjust exponent for rest.
					 * The result is a normalized
					 * number.
					 */
					shift = lzm + 1;
					expon.i = scale_factor.i - lzm;
				}
			/* No leading zeros in mantissa. */
			} else {

				/* Shift by 1 to normalize mantissa. Do
				 * rest of scaling through exponent.
				 */
				shift =	1;
				expon.i = scale_factor.i;
			}
			/* position the exponent. */
			exponent.ui = expon.ui << IEEE_64_MANT_BITS;

			/* scale the mantissa. */
			mantissa.ui = orig_mantissa.ui << shift;

		/* Scale_factor LE 0. */
		} else {

			/* scale mantissa. */
			mantissa.ui = orig_mantissa.ui >> (-scale_factor.i);
			if ((-scale_factor.ui != 0) &&
			    (orig_mantissa.ui & (0x1 <<
			    (-scale_factor.i - 1)))) {
					mantissa.ui++;
			}

		}

		/* mask out any bits that may have shifted to the left of
		 * the mantissa area.
		 */
		mantissa.ui &= IEEE_64_MANTISSA;

		/* OR the new mantissa, the new exponent, and the original
		 * sign bit together to create the result.
		 */
		number.ui = mantissa.ui | exponent.ui | sign_bit.ui;

	} else {
Esempio n. 6
0
_f_real8
_IEEE_REMAINDER_R_R(_f_real8 argx, _f_real8 argy)
{
	/* Union defined to work with IEEE 64-bit floating point. */
	union _ieee_double {
		struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN
                    unsigned int mantissa_lo : IEEE_64_MANT_BITS_H2;
                    unsigned int mantissa_up : IEEE_64_MANT_BITS_H1;
                    unsigned int exponent    : IEEE_64_EXPO_BITS;
                    unsigned int sign        : 1;
#else
                    unsigned int sign        : 1;
                    unsigned int exponent    : IEEE_64_EXPO_BITS;
                    unsigned int mantissa_up : IEEE_64_MANT_BITS_H1;
                    unsigned int mantissa_lo : IEEE_64_MANT_BITS_H2;
#endif
		} parts1;
		_f_real8		dword;
		unsigned int		lword[2];
		unsigned long long	llword;
		long long		int64;
	};
#if __BYTE_ORDER == __LITTLE_ENDIAN
        const int lword_hi = 1;
        const int lword_lo = 0;
#else
        const int lword_hi = 0;
        const int lword_lo = 1;
#endif

	_f_real8	scalet, scaley;
	unsigned int	sign_x = 0X80000000;
	unsigned int	even_x = 0X00000001;
	union _ieee_double x_val, y_val, tdiv, two_52, evenchk, div_52;
	union _ieee_double nearint, y_up, y_lo, tdiv_up, tdiv_lo, res;
	x_val.dword	= argx;
	y_val.dword	= argy;
	two_52.lword[lword_hi] = 0x43300000;	/* 2**52	*/
	two_52.lword[lword_lo] = 0x00000000;
	div_52.lword[lword_hi] = 0x3CB00000;	/* 2**-52	*/
	div_52.lword[lword_lo] = 0x00000000;

	/* check input values: x for infinity and y for zero. */
	if (((x_val.llword & ~IEEE_64_SIGN_BIT) == IEEE_64_INFINITY) ||
	   ((!(isnan64(y_val.dword))) && (y_val.dword == 0.0))) {
		union _ieee_double x_val;
		_f_real8	result8;
		_f_real8	arg8 = 0.0;

		x_val.llword	= _SGL_NaN;

		/* need to emit invalid exception */
		result8		= _raisinvld(arg8, arg8);
		return(x_val.dword);
	}
	tdiv.dword	= argx / argy;

	/* check for 2**52 or greater = already integer */
	if ((int) (tdiv.lword[lword_hi] & (~sign_x)) < (int) two_52.lword[lword_hi]) {

		/* calculate fraction */
		evenchk.dword =
			tdiv.dword - (_f_real8)((_f_int8)tdiv.dword);

		if (tdiv.dword < 0.0) {
			nearint.int64 = (_f_int8) (tdiv.dword - 0.5);
			if ((evenchk.dword == -0.5) &&
			    ((nearint.lword[lword_lo] & even_x) != 0))
				nearint.int64 += 1;
		} else {
			nearint.int64 = (_f_int8) (tdiv.dword + 0.5);
			if ((evenchk.dword == 0.5) &&
			   ((nearint.lword[lword_lo] & even_x) != 0))
				nearint.int64 -= 1;
		}
		tdiv.dword = (_f_real8) nearint.int64;
	}

	/* Calculate upper and lower for y and tdiv. */
	y_up.dword = y_val.dword;
	tdiv_up.dword = tdiv.dword;
	y_up.parts1.mantissa_lo = 0x0;
	tdiv_up.parts1.mantissa_lo = 0x0;
	scalet = 1.0;
	scaley = 1.0;

	/* If tdiv_up exponent < 27, scale up to prevent underflow. */
	if ((int) tdiv.parts1.exponent < 27) {
		tdiv_lo.dword = (tdiv.dword * two_52.dword) -
			(tdiv_up.dword * two_52.dword);
		scalet = div_52.dword;
	} else
		tdiv_lo.dword = tdiv.dword - tdiv_up.dword;

	/* If y_up exponent < 27, scale up to prevent underflow. */
	if ((int) y_val.parts1.exponent < 27) {
		y_lo.dword = (y_val.dword * two_52.dword) -
			(y_val.dword * two_52.dword);
		scaley = div_52.dword;
	} else
		y_lo.dword = y_val.dword - y_up.dword;

	/* algorithm for ieee for x - (x/y)*y. */
	res.dword = ((((x_val.dword - (tdiv_up.dword * y_up.dword)) -
			(scaley * (tdiv_up.dword * y_lo.dword))) -
			(scalet * (tdiv_lo.dword * y_up.dword))) -
		(scalet * scaley * (tdiv_lo.dword * y_lo.dword)));
	if (res.dword == 0.0)
		res.parts1.sign = x_val.parts1.sign;
	return(res.dword);
}
Esempio n. 7
0
_f_log8 _IEEE_IS_NAN_L8( _f_real8 x)
{
	/* if x is NaN, return TRUE */
	return ((_f_log8) _btol(isnan64(x)));
}