summaryrefslogtreecommitdiff
path: root/libraries/base/GHC/Float.hs
diff options
context:
space:
mode:
authorARATA Mizuki <minorinoki@gmail.com>2021-01-14 22:58:45 +0900
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-03-17 19:05:13 -0400
commit540fa6b2cff3802877ff56a47ab3611e33a9ac86 (patch)
tree3cb8a8448170e96ec1d0fadee138cd6a4e58249b /libraries/base/GHC/Float.hs
parentf11954b16c07703b5444eda4a8ab16eadaedc7e6 (diff)
downloadhaskell-540fa6b2cff3802877ff56a47ab3611e33a9ac86.tar.gz
fromInteger :: Integer -> {Float,Double} now always round to nearest even
integerToFloat# and integerToDouble# were moved from ghc-bignum to base. GHC.Integer.floatFromInteger and doubleFromInteger were removed. Fixes #15926, #17231, #17782
Diffstat (limited to 'libraries/base/GHC/Float.hs')
-rw-r--r--libraries/base/GHC/Float.hs54
1 files changed, 52 insertions, 2 deletions
diff --git a/libraries/base/GHC/Float.hs b/libraries/base/GHC/Float.hs
index cb1ef6044c..e5ecc94045 100644
--- a/libraries/base/GHC/Float.hs
+++ b/libraries/base/GHC/Float.hs
@@ -1,5 +1,6 @@
{-# LANGUAGE Trustworthy #-}
-{-# LANGUAGE CPP
+{-# LANGUAGE BangPatterns
+ , CPP
, GHCForeignImportPrim
, NoImplicitPrelude
, MagicHash
@@ -299,6 +300,15 @@ instance Num Float where
{-# INLINE fromInteger #-}
fromInteger i = F# (integerToFloat# i)
+-- | Convert an Integer to a Float#
+integerToFloat# :: Integer -> Float#
+{-# NOINLINE integerToFloat# #-}
+integerToFloat# (IS i) = int2Float# i
+integerToFloat# i@(IP _) = case integerToBinaryFloat' i of
+ F# x -> x
+integerToFloat# (IN bn) = case integerToBinaryFloat' (IP bn) of
+ F# x -> negateFloat# x
+
-- | @since 2.01
instance Real Float where
toRational (F# x#) =
@@ -494,6 +504,14 @@ instance Num Double where
{-# INLINE fromInteger #-}
fromInteger i = D# (integerToDouble# i)
+-- | Convert an Integer to a Double#
+integerToDouble# :: Integer -> Double#
+{-# NOINLINE integerToDouble# #-}
+integerToDouble# (IS i) = int2Double# i
+integerToDouble# i@(IP _) = case integerToBinaryFloat' i of
+ D# x -> x
+integerToDouble# (IN bn) = case integerToBinaryFloat' (IP bn) of
+ D# x -> negateDouble# x
-- | @since 2.01
instance Real Double where
@@ -920,7 +938,39 @@ floatToDigits base x =
(map fromIntegral (reverse rds), k)
------------------------------------------------------------------------
--- Converting from a Rational to a RealFloa
+-- Converting from an Integer to a RealFloat
+------------------------------------------------------------------------
+
+{-# SPECIALISE integerToBinaryFloat' :: Integer -> Float,
+ Integer -> Double #-}
+-- | Converts a positive integer to a floating-point value.
+--
+-- The value nearest to the argument will be returned.
+-- If there are two such values, the one with an even significand will
+-- be returned (i.e. IEEE roundTiesToEven).
+--
+-- The argument must be strictly positive, and @floatRadix (undefined :: a)@ must be 2.
+integerToBinaryFloat' :: RealFloat a => Integer -> a
+integerToBinaryFloat' n = result
+ where
+ mantDigs = floatDigits result
+ k = I# (word2Int# (integerLog2# n))
+ result = if k < mantDigs then
+ encodeFloat n 0
+ else
+ let !e@(I# e#) = k - mantDigs + 1
+ q = n `unsafeShiftR` e
+ n' = case roundingMode# n (e# -# 1#) of
+ 0# -> q
+ 1# -> if integerToInt q .&. 1 == 0 then
+ q
+ else
+ q + 1
+ _ {- 2# -} -> q + 1
+ in encodeFloat n' e
+
+------------------------------------------------------------------------
+-- Converting from a Rational to a RealFloat
------------------------------------------------------------------------
{-