diff options
Diffstat (limited to 'libraries/base/GHC/Float.hs')
-rw-r--r-- | libraries/base/GHC/Float.hs | 118 |
1 files changed, 79 insertions, 39 deletions
diff --git a/libraries/base/GHC/Float.hs b/libraries/base/GHC/Float.hs index 2f21daa57f..67cc11f9a9 100644 --- a/libraries/base/GHC/Float.hs +++ b/libraries/base/GHC/Float.hs @@ -32,6 +32,17 @@ #include "ieee-flpt.h" #include "MachDeps.h" +#if WORD_SIZE_IN_BITS == 32 +# define WSHIFT 5 +# define MMASK 31 +#elif WORD_SIZE_IN_BITS == 64 +# define WSHIFT 6 +# define MMASK 63 +#else +# error unsupported WORD_SIZE_IN_BITS +#endif + + module GHC.Float ( module GHC.Float , Float(..), Double(..), Float#, Double# @@ -55,8 +66,7 @@ import GHC.Word import GHC.Arr import GHC.Float.RealFracMethods import GHC.Float.ConversionUtils -import GHC.Integer.Logarithms ( integerLogBase# ) -import GHC.Integer.Logarithms.Internals +import GHC.Num.BigNat infixr 8 ** @@ -284,7 +294,7 @@ instance Num Float where | otherwise = x -- handles 0.0, (-0.0), and NaN {-# INLINE fromInteger #-} - fromInteger i = F# (floatFromInteger i) + fromInteger i = F# (integerToFloat# i) -- | @since 2.01 instance Real Float where @@ -292,12 +302,12 @@ instance Real Float where case decodeFloat_Int# x# of (# m#, e# #) | isTrue# (e# >=# 0#) -> - (smallInteger m# `shiftLInteger` e#) :% 1 + (IS m# `integerShiftL#` int2Word# e#) :% 1 | isTrue# ((int2Word# m# `and#` 1##) `eqWord#` 0##) -> case elimZerosInt# m# (negateInt# e#) of - (# n, d# #) -> n :% shiftLInteger 1 d# + (# n, d# #) -> n :% integerShiftL# 1 (int2Word# d#) | otherwise -> - smallInteger m# :% shiftLInteger 1 (negateInt# e#) + IS m# :% integerShiftL# 1 (int2Word# (negateInt# e#)) -- | @since 2.01 -- Note that due to the presence of @NaN@, not all elements of 'Float' have an @@ -422,9 +432,9 @@ instance RealFloat Float where floatRange _ = (FLT_MIN_EXP, FLT_MAX_EXP) -- ditto decodeFloat (F# f#) = case decodeFloat_Int# f# of - (# i, e #) -> (smallInteger i, I# e) + (# i, e #) -> (IS i, I# e) - encodeFloat i (I# e) = F# (encodeFloatInteger i e) + encodeFloat i (I# e) = F# (integerEncodeFloat# i e) exponent x = case decodeFloat x of (m,n) -> if m == 0 then 0 else n + floatDigits x @@ -479,21 +489,21 @@ instance Num Double where {-# INLINE fromInteger #-} - fromInteger i = D# (doubleFromInteger i) + fromInteger i = D# (integerToDouble# i) -- | @since 2.01 instance Real Double where toRational (D# x#) = - case decodeDoubleInteger x# of + case integerDecodeDouble# x# of (# m, e# #) | isTrue# (e# >=# 0#) -> - shiftLInteger m e# :% 1 - | isTrue# ((integerToWord m `and#` 1##) `eqWord#` 0##) -> + integerShiftL# m (int2Word# e#) :% 1 + | isTrue# ((integerToWord# m `and#` 1##) `eqWord#` 0##) -> case elimZerosInteger m (negateInt# e#) of - (# n, d# #) -> n :% shiftLInteger 1 d# + (# n, d# #) -> n :% integerShiftL# 1 (int2Word# d#) | otherwise -> - m :% shiftLInteger 1 (negateInt# e#) + m :% integerShiftL# 1 (int2Word# (negateInt# e#)) -- | @since 2.01 -- Note that due to the presence of @NaN@, not all elements of 'Double' have an @@ -611,10 +621,10 @@ instance RealFloat Double where floatRange _ = (DBL_MIN_EXP, DBL_MAX_EXP) -- ditto decodeFloat (D# x#) - = case decodeDoubleInteger x# of + = case integerDecodeDouble# x# of (# i, j #) -> (i, I# j) - encodeFloat i (I# j) = D# (encodeDoubleInteger i j) + encodeFloat i (I# j) = D# (integerEncodeDouble# i j) exponent x = case decodeFloat x of (m,n) -> if m == 0 then 0 else n + floatDigits x @@ -995,7 +1005,9 @@ fromRat' x = r (minExp0, _) = floatRange r minExp = minExp0 - p -- the real minimum exponent xMax = toRational (expt b p) - p0 = (integerLogBase b (numerator x) - integerLogBase b (denominator x) - p) `max` minExp + ln = I# (word2Int# (integerLogBase# b (numerator x))) + ld = I# (word2Int# (integerLogBase# b (denominator x))) + p0 = (ln - ld - p) `max` minExp -- if x = n/d and ln = integerLogBase b n, ld = integerLogBase b d, -- then b^(ln-ld-1) < x < b^(ln-ld+1) f = if p0 < 0 then 1 :% expt b (-p0) else expt b p0 :% 1 @@ -1029,18 +1041,6 @@ maxExpt10 = 324 expts10 :: Array Int Integer expts10 = array (minExpt,maxExpt10) [(n,10^n) | n <- [minExpt .. maxExpt10]] --- Compute the (floor of the) log of i in base b. --- Simplest way would be just divide i by b until it's smaller then b, but that would --- be very slow! We are just slightly more clever, except for base 2, where --- we take advantage of the representation of Integers. --- The general case could be improved by a lookup table for --- approximating the result by integerLog2 i / integerLog2 b. -integerLogBase :: Integer -> Integer -> Int -integerLogBase b i - | i < b = 0 - | b == 2 = I# (integerLog2# i) - | otherwise = I# (integerLogBase# b i) - {- Unfortunately, the old conversion code was awfully slow due to a) a slow integer logarithm @@ -1061,10 +1061,10 @@ divisions as much as possible. fromRat'' :: RealFloat a => Int -> Int -> Integer -> Integer -> a -- Invariant: n and d strictly positive fromRat'' minEx@(I# me#) mantDigs@(I# md#) n d = - case integerLog2IsPowerOf2# d of - (# ld#, pw# #) - | isTrue# (pw# ==# 0#) -> - case integerLog2# n of + case integerIsPowerOf2# d of + (# | ldw# #) -> + let ld# = word2Int# ldw# + in case word2Int# (integerLog2# n) of ln# | isTrue# (ln# >=# (ld# +# me# -# 1#)) -> -- this means n/d >= 2^(minEx-1), i.e. we are guaranteed to get -- a normalised number, round to mantDigs bits @@ -1095,12 +1095,12 @@ fromRat'' minEx@(I# me#) mantDigs@(I# md#) n d = _ -> encodeFloat (n' + 1) (minEx-mantDigs) | isTrue# (ld'# ># (ln# +# 1#)) -> encodeFloat 0 0 -- result of shift < 0.5 | otherwise -> -- first bit of n shifted to 0.5 place - case integerLog2IsPowerOf2# n of - (# _, 0# #) -> encodeFloat 0 0 -- round to even - (# _, _ #) -> encodeFloat 1 (minEx - mantDigs) - | otherwise -> - let ln = I# (integerLog2# n) - ld = I# ld# + case integerIsPowerOf2# n of + (# | _ #) -> encodeFloat 0 0 -- round to even + (# () | #) -> encodeFloat 1 (minEx - mantDigs) + (# () | #) -> + let ln = I# (word2Int# (integerLog2# n)) + ld = I# (word2Int# (integerLog2# d)) -- 2^(ln-ld-1) < n/d < 2^(ln-ld+1) p0 = max minEx (ln - ld) (n', d') @@ -1123,6 +1123,46 @@ fromRat'' minEx@(I# me#) mantDigs@(I# md#) n d = GT -> q+1 in encodeFloat rdq p' +-- Assumption: Integer and Int# are strictly positive, Int# is less +-- than logBase 2 of Integer, otherwise havoc ensues. +-- Used only for the numerator in fromRational when the denominator +-- is a power of 2. +-- The Int# argument is log2 n minus the number of bits in the mantissa +-- of the target type, i.e. the index of the first non-integral bit in +-- the quotient. +-- +-- 0# means round down (towards zero) +-- 1# means we have a half-integer, round to even +-- 2# means round up (away from zero) +roundingMode# :: Integer -> Int# -> Int# +roundingMode# (IS i#) t = + let + k = int2Word# i# `and#` ((uncheckedShiftL# 2## t) `minusWord#` 1##) + c = uncheckedShiftL# 1## t + in if isTrue# (c `gtWord#` k) + then 0# + else if isTrue# (c `ltWord#` k) + then 2# + else 1# + +roundingMode# (IN bn) t = roundingMode# (IP bn) t -- dummy +roundingMode# (IP bn) t = + let + j = word2Int# (int2Word# t `and#` MMASK##) -- index of relevant bit in word + k = uncheckedIShiftRA# t WSHIFT# -- index of relevant word + r = bigNatIndex# bn k `and#` ((uncheckedShiftL# 2## j) `minusWord#` 1##) + c = uncheckedShiftL# 1## j + test i = if isTrue# (i <# 0#) + then 1# + else case bigNatIndex# bn i of + 0## -> test (i -# 1#) + _ -> 2# + in if isTrue# (c `gtWord#` r) + then 0# + else if isTrue# (c `ltWord#` r) + then 2# + else test (k -# 1#) + ------------------------------------------------------------------------ -- Floating point numeric primops ------------------------------------------------------------------------ |