1 /* -----------------------------------------------------------------------------
3 * (c) Lennart Augustsson
4 * (c) The GHC Team, 1998-2000
6 * Miscellaneous support for floating-point primitives
8 * ---------------------------------------------------------------------------*/
10 #include "PosixSource.h"
13 #include "StgPrimFloat.h"
18 #define IEEE_FLOATING_POINT 1
21 # error FLT_RADIX != 2 not supported
25 * Encoding and decoding Doubles. Code based on the HBC code
29 #if IEEE_FLOATING_POINT
30 #define MY_DMINEXP ((DBL_MIN_EXP) - (DBL_MANT_DIG) - 1)
31 /* DMINEXP is defined in values.h on Linux (for example) */
32 #define DHIGHBIT 0x00100000
33 #define DMSBIT 0x80000000
35 #define MY_FMINEXP ((FLT_MIN_EXP) - (FLT_MANT_DIG) - 1)
36 #define FHIGHBIT 0x00800000
37 #define FMSBIT 0x80000000
40 #if defined(WORDS_BIGENDIAN) || defined(FLOAT_WORDS_BIGENDIAN)
48 #define __abs(a) (( (a) >= 0 ) ? (a) : (-(a)))
50 /* Special version for words */
52 __word_encodeDouble (W_ j
, I_ e
)
58 /* Now raise to the exponent */
59 if ( r
!= 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
65 /* Special version for small Integers */
67 __int_encodeDouble (I_ j
, I_ e
)
71 r
= (StgDouble
)__abs(j
);
73 /* Now raise to the exponent */
74 if ( r
!= 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
77 /* sign is encoded in the size */
84 /* Special version for small Integers */
86 __int_encodeFloat (I_ j
, I_ e
)
90 r
= (StgFloat
)__abs(j
);
92 /* Now raise to the exponent */
93 if ( r
!= 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
96 /* sign is encoded in the size */
103 /* Special version for small positive Integers */
105 __word_encodeFloat (W_ j
, I_ e
)
111 /* Now raise to the exponent */
112 if ( r
!= 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
118 /* This only supports IEEE floating point */
121 __decodeDouble_2Int (I_
*man_sign
, W_
*man_high
, W_
*man_low
, I_
*exp
, StgDouble dbl
)
123 /* Do some bit fiddling on IEEE */
124 unsigned int low
, high
; /* assuming 32 bit ints */
126 union { double d
; unsigned int i
[2]; } u
; /* assuming 32 bit ints, 64 bit double */
128 ASSERT(sizeof(unsigned int ) == 4 );
129 ASSERT(sizeof(dbl
) == 8 );
130 ASSERT(sizeof(dbl
) == SIZEOF_DOUBLE
);
132 u
.d
= dbl
; /* grab chunks of the double */
136 if (low
== 0 && (high
& ~DMSBIT
) == 0) {
141 iexp
= ((high
>> 20) & 0x7ff) + MY_DMINEXP
;
145 if (iexp
!= MY_DMINEXP
) /* don't add hidden bit to denorms */
149 /* A denorm, normalize the mantissa */
150 while (! (high
& DHIGHBIT
)) {
161 *man_sign
= (sign
< 0) ?
-1 : 1;
165 /* This is expected to replace uses of __decodeDouble_2Int() in the long run */
167 __decodeDouble_Int64 (StgInt64
*const mantissa
, const StgDouble dbl
)
170 // We can't use this yet as-is, see ticket #9810
173 *mantissa
= (StgInt64
)scalbn(frexp(dbl
, &exp
), DBL_MANT_DIG
);
174 return exp
-DBL_MANT_DIG
;
181 W_ man_high
= 0, man_low
= 0;
184 __decodeDouble_2Int (&man_sign
, &man_high
, &man_low
, &exp
, dbl
);
185 ASSIGN_Int64((W_
*)mantissa
, ((((StgInt64
)man_high
<< 32)
187 * (StgInt64
)man_sign
));
192 /* Convenient union types for checking the layout of IEEE 754 types -
193 based on defs in GNU libc <ieee754.h>
197 __decodeFloat_Int (I_
*man
, I_
*exp
, StgFloat flt
)
199 /* Do some bit fiddling on IEEE */
200 int high
, sign
; /* assuming 32 bit ints */
201 union { float f
; int i
; } u
; /* assuming 32 bit float and int */
203 ASSERT(sizeof(int ) == 4 );
204 ASSERT(sizeof(flt
) == 4 );
205 ASSERT(sizeof(flt
) == SIZEOF_FLOAT
);
207 u
.f
= flt
; /* grab the float */
210 if ((high
& ~FMSBIT
) == 0) {
214 *exp
= ((high
>> 23) & 0xff) + MY_FMINEXP
;
218 if (*exp
!= MY_FMINEXP
) /* don't add hidden bit to denorms */
222 /* A denorm, normalize the mantissa */
223 while (! (high
& FHIGHBIT
)) {