/** Cast to 32 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 32-bit numbers is a 33-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. \param a,b Any 32-bit non-denormalised floating point numbers. \return The unsigned distance between <code>a</code> and <code>b</code> in 'floating point space'. */ unsigned int cbf_ULP32(const float a, const float 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 (isnan32(a) || isinf32(a) || isnan32(b) || isinf32(b)) { if (isinf32(a) && isinf32(b) && a==b) return 0; return 0xffffffff; } else { const unsigned int signmask = 0x80000000; /* cast numbers so that ia >= ib */ unsigned int ia = *(unsigned int *)(a>b ? &a : &b); unsigned int ib = *(unsigned int *)(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; } }
/* if x is zero, return -HUGE */ if (x == 0.0e0) return(-HUGE_INT8_F90); i = __ieee_real4i(x); return ((_f_int8) i); } #else /* _CRAYMPP */ _f_int8 _IEEE_EXPONENT_I8_H(_f_real4 x) { int i; REGISTER_4 s1, s2; /* if x is a NaN, return HUGE */ if (isnan32(x)) return(HUGE_INT8_F90); s1.f = x; /* clear sign bit. */ s1.ui &= ~IEEE_32_SIGN_BIT; /* if x is + or -infinity, return HUGE */ if (s1.ui == IEEE_32_INFINITY) return(HUGE_INT8_F90); /* if x is zero, return -HUGE */ if (x == (float) 0.0e0) return(-HUGE_INT8_F90); /* shift exponent bits to right. */ s1.i >>= IEEE_32_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_32_MANTISSA & s2.ui; /* get leading zeros in mantissa part. */ i = _leadz4(s2.ui) - IEEE_32_EXPO_BITS; /* calculate exponent. */ s1.i -= (IEEE_32_EXPO_BIAS + i); } else { /* subtract exponent bias and implicit bit. */ s1.i -= (IEEE_32_EXPO_BIAS); } return((_f_int8) s1.i); }
inline static /* for the inline version of this function. */ #endif #ifdef _F_REAL4 _f_real4 _FRACTION_4(_f_real4 x) { int lz; REGISTER_4 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_32_INFINITY) return _HALF_NaN; if (isnan32(x)) return x; s1.f = x; /* get sign bit */ sign_bit.ui = IEEE_32_SIGN_BIT & s1.ui; /* get mantissa */ mantissa.ui = IEEE_32_MANTISSA & s1.ui; /* get exponent */ exponent.ui = IEEE_32_EXPONENT & s1.ui; if (exponent.ui == 0x0) { /* number is subnormal. normalize mantissa. */ /* 1. Get leading zeros of mantissa. */ lz = _leadz4(mantissa.ui) - IEEE_32_EXPO_BITS; /* 2. Normalize by shifting out all leading zeros and * first 1 bit. */ mantissa.ui = (mantissa.ui << lz) & IEEE_32_MANTISSA; } /* position the exponent bias less the implicit bit */ exponent.ui = (IEEE_32_EXPO_BIAS - 1) << IEEE_32_MANT_BITS; /* extract fraction. */ s1.ui = exponent.ui | mantissa.ui | sign_bit.ui; return s1.f; }
_f_log8 _IEEE_IS_NAN_L8_H( _f_real4 x) { /* if x is NaN, return TRUE */ return ((_f_log8) _btol(isnan32(x))); }
_f_real4 _IEEE_BINARY_SCALE_H(_f_real4 orig_number, _f_int4 orig_scale_factor) { int lz, lzm, shift; REGISTER_4 number, scale_factor, expon, exponent, orig_mantissa, mantissa, sign_bit; /* if x is a NaN, return a Nan */ if (isnan32(orig_number)) return orig_number; number.f = orig_number; /* extract sign bit. */ sign_bit.ui = IEEE_32_SIGN_BIT & number.ui; /* extract exponent. */ exponent.ui = IEEE_32_EXPONENT & number.ui; /* extract mantissa. */ orig_mantissa.ui = IEEE_32_MANTISSA & number.ui; /* if x is + or -infinity, return same infinity */ number.ui &= ~IEEE_32_SIGN_BIT; if (number.ui == IEEE_32_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 = _leadz4(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_32_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_32_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_32_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 {
_f_real8 _IEEE_REMAINDER_R_H(_f_real8 argx, _f_real4 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 /* Union defined to work with IEEE 32-bit floating point. */ union _ieee_fdouble { _f_real4 fpword; unsigned int l4word; int int32; }; _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; union _ieee_fdouble y4_val; x_val.dword = argx; y4_val.fpword = 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) || ((!(isnan32(y4_val.fpword))) && (y4_val.fpword == 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); } y_val.dword = y4_val.fpword; tdiv.dword = argx / y_val.dword; /* check for 2**52 or greater = already integer */ if ((tdiv.lword[lword_hi] & (~sign_x)) < 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); }