Commit e9fdcd7b authored by Ian Lynagh's avatar Ian Lynagh
Browse files

Fix conversions between Double/Float and simple-integer

parent 920470ae
...@@ -765,6 +765,7 @@ stmtMacros = listToUFM [ ...@@ -765,6 +765,7 @@ stmtMacros = listToUFM [
( fsLit "RET_NPP", \[a,b,c] -> emitRetUT [(NonPtrArg,a),(PtrArg,b),(PtrArg,c)]), ( fsLit "RET_NPP", \[a,b,c] -> emitRetUT [(NonPtrArg,a),(PtrArg,b),(PtrArg,c)]),
( fsLit "RET_NNP", \[a,b,c] -> emitRetUT [(NonPtrArg,a),(NonPtrArg,b),(PtrArg,c)]), ( fsLit "RET_NNP", \[a,b,c] -> emitRetUT [(NonPtrArg,a),(NonPtrArg,b),(PtrArg,c)]),
( fsLit "RET_NNN", \[a,b,c] -> emitRetUT [(NonPtrArg,a),(NonPtrArg,b),(NonPtrArg,c)]), ( fsLit "RET_NNN", \[a,b,c] -> emitRetUT [(NonPtrArg,a),(NonPtrArg,b),(NonPtrArg,c)]),
( fsLit "RET_NNNN", \[a,b,c,d] -> emitRetUT [(NonPtrArg,a),(NonPtrArg,b),(NonPtrArg,c),(NonPtrArg,d)]),
( fsLit "RET_NNNP", \[a,b,c,d] -> emitRetUT [(NonPtrArg,a),(NonPtrArg,b),(NonPtrArg,c),(PtrArg,d)]), ( fsLit "RET_NNNP", \[a,b,c,d] -> emitRetUT [(NonPtrArg,a),(NonPtrArg,b),(NonPtrArg,c),(PtrArg,d)]),
( fsLit "RET_NPNP", \[a,b,c,d] -> emitRetUT [(NonPtrArg,a),(PtrArg,b),(NonPtrArg,c),(PtrArg,d)]) ( fsLit "RET_NPNP", \[a,b,c,d] -> emitRetUT [(NonPtrArg,a),(PtrArg,b),(NonPtrArg,c),(PtrArg,d)])
......
...@@ -619,10 +619,11 @@ primop DoubleDecodeOp "decodeDouble#" GenPrimOp ...@@ -619,10 +619,11 @@ primop DoubleDecodeOp "decodeDouble#" GenPrimOp
with out_of_line = True with out_of_line = True
primop DoubleDecode_2IntOp "decodeDouble_2Int#" GenPrimOp primop DoubleDecode_2IntOp "decodeDouble_2Int#" GenPrimOp
Double# -> (# Int#, Int#, Int# #) Double# -> (# Int#, Word#, Word#, Int# #)
{Convert to arbitrary-precision integer. {Convert to arbitrary-precision integer.
First {\tt Int\#} in result is the high 32 bits of the mantissa, and the First component of the result is -1 or 1, indicating the sign of the
second is the low 32. The third is the exponent.} mantissa. The next two are the high and low 32 bits of the mantissa
respectively, and the last is the exponent.}
with out_of_line = True with out_of_line = True
------------------------------------------------------------------------ ------------------------------------------------------------------------
......
...@@ -206,7 +206,7 @@ extern void stackOverflow(void); ...@@ -206,7 +206,7 @@ extern void stackOverflow(void);
extern void __decodeDouble (MP_INT *man, I_ *_exp, StgDouble dbl); extern void __decodeDouble (MP_INT *man, I_ *_exp, StgDouble dbl);
extern void __decodeFloat (MP_INT *man, I_ *_exp, StgFloat flt); extern void __decodeFloat (MP_INT *man, I_ *_exp, StgFloat flt);
extern void __decodeDouble_2Int (I_ *man_high, I_ *man_low, I_ *exp, StgDouble dbl); extern void __decodeDouble_2Int (I_ *man_sign, W_ *man_high, W_ *man_low, I_ *exp, StgDouble dbl);
extern void __decodeFloat_Int (I_ *man, I_ *exp, StgFloat flt); extern void __decodeFloat_Int (I_ *man, I_ *exp, StgFloat flt);
#if defined(WANT_DOTNET_SUPPORT) #if defined(WANT_DOTNET_SUPPORT)
......
...@@ -50,8 +50,10 @@ extern unsigned int n_capabilities; ...@@ -50,8 +50,10 @@ extern unsigned int n_capabilities;
extern StgDouble __encodeDouble (I_ size, StgByteArray arr, I_ e); extern StgDouble __encodeDouble (I_ size, StgByteArray arr, I_ e);
extern StgDouble __2Int_encodeDouble (I_ j_high, I_ j_low, I_ e); extern StgDouble __2Int_encodeDouble (I_ j_high, I_ j_low, I_ e);
extern StgDouble __int_encodeDouble (I_ j, I_ e); extern StgDouble __int_encodeDouble (I_ j, I_ e);
extern StgDouble __word_encodeDouble (W_ j, I_ e);
extern StgFloat __encodeFloat (I_ size, StgByteArray arr, I_ e); extern StgFloat __encodeFloat (I_ size, StgByteArray arr, I_ e);
extern StgFloat __int_encodeFloat (I_ j, I_ e); extern StgFloat __int_encodeFloat (I_ j, I_ e);
extern StgFloat __word_encodeFloat (W_ j, I_ e);
extern StgInt isDoubleNaN(StgDouble d); extern StgInt isDoubleNaN(StgDouble d);
extern StgInt isDoubleInfinite(StgDouble d); extern StgInt isDoubleInfinite(StgDouble d);
extern StgInt isDoubleDenormalized(StgDouble d); extern StgInt isDoubleDenormalized(StgDouble d);
......
...@@ -537,8 +537,10 @@ typedef struct _RtsSymbolVal { ...@@ -537,8 +537,10 @@ typedef struct _RtsSymbolVal {
SymX(addDLL) \ SymX(addDLL) \
GMP_SYMS \ GMP_SYMS \
SymX(__int_encodeDouble) \ SymX(__int_encodeDouble) \
SymX(__word_encodeDouble) \
SymX(__2Int_encodeDouble) \ SymX(__2Int_encodeDouble) \
SymX(__int_encodeFloat) \ SymX(__int_encodeFloat) \
SymX(__word_encodeFloat) \
SymX(andIntegerzh_fast) \ SymX(andIntegerzh_fast) \
SymX(atomicallyzh_fast) \ SymX(atomicallyzh_fast) \
SymX(barf) \ SymX(barf) \
......
...@@ -928,16 +928,20 @@ decodeDoublezu2Intzh_fast ...@@ -928,16 +928,20 @@ decodeDoublezu2Intzh_fast
W_ p; W_ p;
FETCH_MP_TEMP(mp_tmp1); FETCH_MP_TEMP(mp_tmp1);
FETCH_MP_TEMP(mp_tmp2); FETCH_MP_TEMP(mp_tmp2);
FETCH_MP_TEMP(mp_tmp_w); FETCH_MP_TEMP(mp_result1);
FETCH_MP_TEMP(mp_result2);
/* arguments: D1 = Double# */ /* arguments: D1 = Double# */
arg = D1; arg = D1;
/* Perform the operation */ /* Perform the operation */
foreign "C" __decodeDouble_2Int(mp_tmp1 "ptr", mp_tmp2 "ptr", mp_tmp_w "ptr", arg) []; foreign "C" __decodeDouble_2Int(mp_tmp1 "ptr", mp_tmp2 "ptr",
mp_result1 "ptr", mp_result2 "ptr",
/* returns: (Int# (mant high), Int# (mant low), Int# (expn)) */ arg) [];
RET_NNN(W_[mp_tmp1], W_[mp_tmp2], W_[mp_tmp_w]);
/* returns:
(Int# (mant sign), Word# (mant high), Word# (mant low), Int# (expn)) */
RET_NNNN(W_[mp_tmp1], W_[mp_tmp2], W_[mp_result1], W_[mp_result2]);
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
......
...@@ -103,6 +103,21 @@ __2Int_encodeDouble (I_ j_high, I_ j_low, I_ e) ...@@ -103,6 +103,21 @@ __2Int_encodeDouble (I_ j_high, I_ j_low, I_ e)
return r; return r;
} }
/* Special version for words */
StgDouble
__word_encodeDouble (W_ j, I_ e)
{
StgDouble r;
r = (StgDouble)j;
/* Now raise to the exponent */
if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
r = ldexp(r, e);
return r;
}
/* Special version for small Integers */ /* Special version for small Integers */
StgDouble StgDouble
__int_encodeDouble (I_ j, I_ e) __int_encodeDouble (I_ j, I_ e)
...@@ -163,6 +178,21 @@ __int_encodeFloat (I_ j, I_ e) ...@@ -163,6 +178,21 @@ __int_encodeFloat (I_ j, I_ e)
return r; return r;
} }
/* Special version for small positive Integers */
StgFloat
__word_encodeFloat (W_ j, I_ e)
{
StgFloat r;
r = (StgFloat)j;
/* Now raise to the exponent */
if ( r != 0.0 ) /* Lennart suggests this avoids a bug in MIPS's ldexp */
r = ldexp(r, e);
return r;
}
/* This only supports IEEE floating point */ /* This only supports IEEE floating point */
void void
...@@ -226,7 +256,7 @@ __decodeDouble (MP_INT *man, I_ *exp, StgDouble dbl) ...@@ -226,7 +256,7 @@ __decodeDouble (MP_INT *man, I_ *exp, StgDouble dbl)
} }
void void
__decodeDouble_2Int (I_ *man_high, I_ *man_low, I_ *exp, StgDouble dbl) __decodeDouble_2Int (I_ *man_sign, W_ *man_high, W_ *man_low, I_ *exp, StgDouble dbl)
{ {
/* Do some bit fiddling on IEEE */ /* Do some bit fiddling on IEEE */
unsigned int low, high; /* assuming 32 bit ints */ unsigned int low, high; /* assuming 32 bit ints */
...@@ -266,9 +296,7 @@ __decodeDouble_2Int (I_ *man_high, I_ *man_low, I_ *exp, StgDouble dbl) ...@@ -266,9 +296,7 @@ __decodeDouble_2Int (I_ *man_high, I_ *man_low, I_ *exp, StgDouble dbl)
*exp = (I_) iexp; *exp = (I_) iexp;
*man_low = low; *man_low = low;
*man_high = high; *man_high = high;
if (sign < 0) { *man_sign = (sign < 0) ? -1 : 1;
*man_high = - *man_high;
}
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment