mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
3.1 KiB
85 lines
3.1 KiB
unsigned int _uitrunc(double x) {
|
|
|
|
// _uitrunc converts the IEEE floating point long number x into a 32-bit
|
|
// unsigned int.
|
|
//
|
|
// The result is truncated towards zero, as in the Fortran INT function,
|
|
// regardless of the current rounding mode. If x > 2**32 or is
|
|
// +infinity, the result is 2**32.
|
|
|
|
// Be VERY CAREFUL when compiling this program with an optimizing compiler.
|
|
// The difference NaN-NaN is computed TWICE in order to cause an exception
|
|
// if the input is invalid. Smart compilers may recognize that x-x is 0.0
|
|
// and avoid generating the "fsub". No folding of floating point compu-
|
|
// tations should be done by the compiler!
|
|
|
|
unsigned answer;
|
|
volatile double NanMinusNan;
|
|
union {
|
|
double sum;
|
|
struct {
|
|
unsigned int lo;
|
|
unsigned int hi;
|
|
} ;
|
|
} xshifted;
|
|
|
|
// We are about to declare a magic number, *pf5243 == 2^52 + 2^43 in
|
|
// IEEE format. It needs to have bit 43 set because adding 2^52
|
|
// to a negative number could cause a borrow and in some
|
|
// weird cases (which I can't remember off the top of my head) the
|
|
// borrow could go all the way to the top of the fraction and thus cause
|
|
// the result to be shifted left by one bit, which messes up the lower
|
|
// 32 bits. To summarize: the 2^43 is added so that there will be a bit
|
|
// above bit 2^32 from which a subtract can always borrow. It could
|
|
// be any bit above 2^32.
|
|
//
|
|
// Positive numbers are not affected one way or the other by the 2^43
|
|
// bit.
|
|
|
|
const static unsigned int f5243[2] = {0x00000000, 0x43300800 };
|
|
const static double *pf5243 = (double *)f5243;
|
|
|
|
// fNAN == +NAN (Not A Number) in IEEE format
|
|
|
|
const static unsigned int fNAN[2] = { 0x00000000, 0x7ff00000 };
|
|
const static double *pfNAN = (double *)fNAN;
|
|
|
|
const static double LargestUnsignedInt = 4294967295.0;
|
|
const static double DoubleZero = 0.0;
|
|
|
|
// If x is NaN or is negative, set the bit for invalid IEEE exception.
|
|
// Because NanMinusNan is volatile the assignment will not removed by
|
|
// dead store elimination. The status is set as for a compare-ordered
|
|
// of x with zero, and the integer result is undefined (ie. FPCC and
|
|
// VXVC are set, and VXSNAN may be). I am not sure what this SHOULD do
|
|
// for the ill-defined cases; the above is a guess at what IEEE dictates,
|
|
// if anything (HSW 6/87).
|
|
|
|
if (( x != x ) || (x < DoubleZero)) {
|
|
NanMinusNan = *pfNAN - *pfNAN;
|
|
return(0);
|
|
}
|
|
|
|
// If x is too big, we can't convert it, either
|
|
|
|
if (x > LargestUnsignedInt) {
|
|
NanMinusNan = *pfNAN - *pfNAN;
|
|
return(0xffffffff);
|
|
}
|
|
else if (x == LargestUnsignedInt)
|
|
return(0xffffffff);
|
|
|
|
// Add the magic number; see the introductory note. The following
|
|
// mysterious comment appears in the original:
|
|
// 51 - 31 = 20, thus shift the integer part right by 20
|
|
|
|
xshifted.sum = x + *pf5243;
|
|
answer = xshifted.lo;
|
|
|
|
// If result was > x, it must have been rounded up. Correct by
|
|
// subtracting one.
|
|
|
|
if ((xshifted.sum - *pf5243) > x ) return answer - 1;
|
|
return answer;
|
|
}
|
|
|