diff options
author | Simon Marlow <marlowsd@gmail.com> | 2009-08-01 22:07:43 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2009-08-01 22:07:43 +0000 |
commit | 5f54b854776ab7a2e172054b2184c56156f14467 (patch) | |
tree | 760386aff94e2a9557ebb3d6867671b895c435f1 /libraries/base/cbits/primFloat.c | |
parent | 14ca5740ee951dc68b59ebaff8a4a6315436333f (diff) | |
download | haskell-5f54b854776ab7a2e172054b2184c56156f14467.tar.gz |
Updates to follow the RTS tidyup
C functions like isDoubleNaN moved here (primFloat.c)
Diffstat (limited to 'libraries/base/cbits/primFloat.c')
-rw-r--r-- | libraries/base/cbits/primFloat.c | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/libraries/base/cbits/primFloat.c b/libraries/base/cbits/primFloat.c new file mode 100644 index 0000000000..3fa39d3c59 --- /dev/null +++ b/libraries/base/cbits/primFloat.c @@ -0,0 +1,261 @@ +/* ----------------------------------------------------------------------------- + * + * (c) Lennart Augustsson + * (c) The GHC Team, 1998-2000 + * + * Miscellaneous support for floating-point primitives + * + * ---------------------------------------------------------------------------*/ + +#include "HsFFI.h" +#include "Rts.h" // XXX wrong (for IEEE_FLOATING_POINT and WORDS_BIGENDIAN) + +#define IEEE_FLOATING_POINT 1 + +union stg_ieee754_flt +{ + float f; + struct { + +#if WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int mantissa:23; +#else + unsigned int mantissa:23; + unsigned int exponent:8; + unsigned int negative:1; +#endif + } ieee; + struct { + +#if WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int quiet_nan:1; + unsigned int mantissa:22; +#else + unsigned int mantissa:22; + unsigned int quiet_nan:1; + unsigned int exponent:8; + unsigned int negative:1; +#endif + } ieee_nan; +}; + +/* + + To recap, here's the representation of a double precision + IEEE floating point number: + + sign 63 sign bit (0==positive, 1==negative) + exponent 62-52 exponent (biased by 1023) + fraction 51-0 fraction (bits to right of binary point) +*/ + +union stg_ieee754_dbl +{ + double d; + struct { + +#if WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:11; + unsigned int mantissa0:20; + unsigned int mantissa1:32; +#else +#if FLOAT_WORDS_BIGENDIAN + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; + unsigned int mantissa1:32; +#else + unsigned int mantissa1:32; + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; +#endif +#endif + } ieee; + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct { + +#if WORDS_BIGENDIAN + unsigned int negative:1; + unsigned int exponent:11; + unsigned int quiet_nan:1; + unsigned int mantissa0:19; + unsigned int mantissa1:32; +#else +#if FLOAT_WORDS_BIGENDIAN + unsigned int mantissa0:19; + unsigned int quiet_nan:1; + unsigned int exponent:11; + unsigned int negative:1; + unsigned int mantissa1:32; +#else + unsigned int mantissa1:32; + unsigned int mantissa0:19; + unsigned int quiet_nan:1; + unsigned int exponent:11; + unsigned int negative:1; +#endif +#endif + } ieee_nan; +}; + +/* + * Predicates for testing for extreme IEEE fp values. + */ + +/* In case you don't suppport IEEE, you'll just get dummy defs.. */ +#ifdef IEEE_FLOATING_POINT + +HsInt +isDoubleNaN(HsDouble d) +{ + union stg_ieee754_dbl u; + + u.d = d; + + return ( + u.ieee.exponent == 2047 /* 2^11 - 1 */ && /* Is the exponent all ones? */ + (u.ieee.mantissa0 != 0 || u.ieee.mantissa1 != 0) + /* and the mantissa non-zero? */ + ); +} + +HsInt +isDoubleInfinite(HsDouble d) +{ + union stg_ieee754_dbl u; + + u.d = d; + + /* Inf iff exponent is all ones, mantissa all zeros */ + return ( + u.ieee.exponent == 2047 /* 2^11 - 1 */ && + u.ieee.mantissa0 == 0 && + u.ieee.mantissa1 == 0 + ); +} + +HsInt +isDoubleDenormalized(HsDouble d) +{ + union stg_ieee754_dbl u; + + u.d = d; + + /* A (single/double/quad) precision floating point number + is denormalised iff: + - exponent is zero + - mantissa is non-zero. + - (don't care about setting of sign bit.) + + */ + return ( + u.ieee.exponent == 0 && + (u.ieee.mantissa0 != 0 || + u.ieee.mantissa1 != 0) + ); + +} + +HsInt +isDoubleNegativeZero(HsDouble d) +{ + union stg_ieee754_dbl u; + + u.d = d; + /* sign (bit 63) set (only) => negative zero */ + + return ( + u.ieee.negative == 1 && + u.ieee.exponent == 0 && + u.ieee.mantissa0 == 0 && + u.ieee.mantissa1 == 0); +} + +/* Same tests, this time for HsFloats. */ + +/* + To recap, here's the representation of a single precision + IEEE floating point number: + + sign 31 sign bit (0 == positive, 1 == negative) + exponent 30-23 exponent (biased by 127) + fraction 22-0 fraction (bits to right of binary point) +*/ + + +HsInt +isFloatNaN(HsFloat f) +{ + union stg_ieee754_flt u; + u.f = f; + + /* Floating point NaN iff exponent is all ones, mantissa is + non-zero (but see below.) */ + return ( + u.ieee.exponent == 255 /* 2^8 - 1 */ && + u.ieee.mantissa != 0); +} + +HsInt +isFloatInfinite(HsFloat f) +{ + union stg_ieee754_flt u; + u.f = f; + + /* A float is Inf iff exponent is max (all ones), + and mantissa is min(all zeros.) */ + return ( + u.ieee.exponent == 255 /* 2^8 - 1 */ && + u.ieee.mantissa == 0); +} + +HsInt +isFloatDenormalized(HsFloat f) +{ + union stg_ieee754_flt u; + u.f = f; + + /* A (single/double/quad) precision floating point number + is denormalised iff: + - exponent is zero + - mantissa is non-zero. + - (don't care about setting of sign bit.) + + */ + return ( + u.ieee.exponent == 0 && + u.ieee.mantissa != 0); +} + +HsInt +isFloatNegativeZero(HsFloat f) +{ + union stg_ieee754_flt u; + u.f = f; + + /* sign (bit 31) set (only) => negative zero */ + return ( + u.ieee.negative && + u.ieee.exponent == 0 && + u.ieee.mantissa == 0); +} + +#else /* ! IEEE_FLOATING_POINT */ + +/* Dummy definitions of predicates - they all return false */ +HsInt isDoubleNaN(d) HsDouble d; { return 0; } +HsInt isDoubleInfinite(d) HsDouble d; { return 0; } +HsInt isDoubleDenormalized(d) HsDouble d; { return 0; } +HsInt isDoubleNegativeZero(d) HsDouble d; { return 0; } +HsInt isFloatNaN(f) HsFloat f; { return 0; } +HsInt isFloatInfinite(f) HsFloat f; { return 0; } +HsInt isFloatDenormalized(f) HsFloat f; { return 0; } +HsInt isFloatNegativeZero(f) HsFloat f; { return 0; } + +#endif /* ! IEEE_FLOATING_POINT */ |