diff options
Diffstat (limited to 'src/libfmt/nan64.c')
-rw-r--r-- | src/libfmt/nan64.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/libfmt/nan64.c b/src/libfmt/nan64.c new file mode 100644 index 00000000..dbd03fc6 --- /dev/null +++ b/src/libfmt/nan64.c @@ -0,0 +1,72 @@ +/* + * 64-bit IEEE not-a-number routines. + * This is big/little-endian portable assuming that + * the 64-bit doubles and 64-bit integers have the + * same byte ordering. + */ + +#include "nan.h" + +typedef unsigned long long uvlong; +typedef unsigned long ulong; + +#ifdef NEEDLL +static uvlong uvnan = 0x7FF0000000000001LL; +static uvlong uvinf = 0x7FF0000000000000LL; +static uvlong uvneginf = 0xFFF0000000000000LL; +#else +static uvlong uvnan = 0x7FF0000000000001; +static uvlong uvinf = 0x7FF0000000000000; +static uvlong uvneginf = 0xFFF0000000000000; +#endif + +double +__NaN(void) +{ + uvlong *p; + + /* gcc complains about "return *(double*)&uvnan;" */ + p = &uvnan; + return *(double*)p; +} + +int +__isNaN(double d) +{ + uvlong x; + double *p; + + p = &d; + x = *(uvlong*)p; + return (ulong)(x>>32)==0x7FF00000 && !__isInf(d, 0); +} + +double +__Inf(int sign) +{ + uvlong *p; + + if(sign < 0) + p = &uvinf; + else + p = &uvneginf; + return *(double*)p; +} + +int +__isInf(double d, int sign) +{ + uvlong x; + double *p; + + p = &d; + x = *(uvlong*)p; + if(sign == 0) + return x==uvinf || x==uvneginf; + else if(sign > 0) + return x==uvinf; + else + return x==uvneginf; +} + + |