[project @ 2001-12-28 22:58:17 by sof]
[ghc-hetmet.git] / ghc / lib / std / PrelFloat.lhs
index 3d202c7..e2172ba 100644 (file)
@@ -1,5 +1,5 @@
 % ------------------------------------------------------------------------------
-% $Id: PrelFloat.lhs,v 1.9 2000/08/29 16:37:35 simonpj Exp $
+% $Id: PrelFloat.lhs,v 1.14 2001/11/20 14:12:48 simonpj Exp $
 %
 % (c) The University of Glasgow, 1994-2000
 %
@@ -151,9 +151,6 @@ instance  Num Float  where
        -- fromInteger in turn inlines,
        -- so that if fromInteger is applied to an (S# i) the right thing happens
 
-    {-# INLINE fromInt #-}
-    fromInt i          =  int2Float i
-
 instance  Real Float  where
     toRational x       =  (m%1)*(b%1)^^n
                           where (m,n) = decodeFloat x
@@ -293,8 +290,9 @@ instance  Num Double  where
 
     {-# INLINE fromInteger #-}
        -- See comments with Num Float
-    fromInteger n      =  encodeFloat n 0
-    fromInt (I# n#)    =  case (int2Double# n#) of { d# -> D# d# }
+    fromInteger (S# i#)    = case (int2Double# i#) of { d# -> D# d# }
+    fromInteger (J# s# d#) = encodeDouble# s# d# 0
+
 
 instance  Real Double  where
     toRational x       =  (m%1)*(b%1)^^n
@@ -426,17 +424,17 @@ for these (@numericEnumFromTo@ and @numericEnumFromThenTo@ below.)
 instance  Enum Float  where
     succ x        = x + 1
     pred x        = x - 1
-    toEnum         =  fromInt
-    fromEnum       =  fromInteger . truncate   -- may overflow
-    enumFrom      =  numericEnumFrom
-    enumFromTo     =  numericEnumFromTo
-    enumFromThen   =  numericEnumFromThen
-    enumFromThenTo =  numericEnumFromThenTo
+    toEnum         = int2Float
+    fromEnum       = fromInteger . truncate   -- may overflow
+    enumFrom      = numericEnumFrom
+    enumFromTo     = numericEnumFromTo
+    enumFromThen   = numericEnumFromThen
+    enumFromThenTo = numericEnumFromThenTo
 
 instance  Enum Double  where
     succ x        = x + 1
     pred x        = x - 1
-    toEnum         =  fromInt
+    toEnum         =  int2Double
     fromEnum       =  fromInteger . truncate   -- may overflow
     enumFrom      =  numericEnumFrom
     enumFromTo     =  numericEnumFromTo
@@ -498,13 +496,15 @@ formatRealFloat fmt decs x
        mk0 ls = case ls of { "" -> "0" ; _ -> ls}
       in
       case decs of
-       Nothing ->
-         let
-         f 0 s    rs  = mk0 (reverse s) ++ '.':mk0 rs
-         f n s    ""  = f (n-1) ('0':s) ""
-         f n s (r:rs) = f (n-1) (r:s) rs
-        in
-        f e "" ds
+       Nothing
+         | e <= 0    -> "0." ++ replicate (-e) '0' ++ ds
+         | otherwise ->
+            let
+               f 0 s    rs  = mk0 (reverse s) ++ '.':mk0 rs
+               f n s    ""  = f (n-1) ('0':s) ""
+               f n s (r:rs) = f (n-1) (r:s) rs
+            in
+               f e "" ds
        Just dec ->
         let dec' = max dec 0 in
        if e >= 0 then
@@ -518,8 +518,8 @@ formatRealFloat fmt decs x
          (ei,is') = roundTo base dec' (replicate (-e) 0 ++ is)
          d:ds' = map intToDigit (if ei > 0 then is' else 0:is')
         in
-        d : '.' : ds'
-        
+        d : (if null ds' then "" else '.':ds')
+
 
 roundTo :: Int -> Int -> [Int] -> (Int,[Int])
 roundTo base d is =
@@ -538,13 +538,18 @@ roundTo base d is =
        (c,ds) = f (n-1) xs
        i'     = c + i
 
---
 -- Based on "Printing Floating-Point Numbers Quickly and Accurately"
 -- by R.G. Burger and R.K. Dybvig in PLDI 96.
 -- This version uses a much slower logarithm estimator. It should be improved.
 
--- This function returns a list of digits (Ints in [0..base-1]) and an
--- exponent.
+-- floatToDigits takes a base and a non-negative RealFloat number,
+-- and returns a list of digits and an exponent. 
+-- In particular, if x>=0, and
+--     floatToDigits base x = ([d1,d2,...,dn], e)
+-- then
+--     (a) n >= 1
+--     (b) x = 0.d1d2...dn * (base**e)
+--     (c) 0 <= di <= base-1
 
 floatToDigits :: (RealFloat a) => Integer -> a -> ([Int], Int)
 floatToDigits _ 0 = ([0], 0)
@@ -583,7 +588,7 @@ floatToDigits base x =
        (p - 1 + e0) * 3 `div` 10
      else
         ceiling ((log (fromInteger (f+1)) +
-                fromInt e * log (fromInteger b)) /
+                fromInteger (int2Integer e) * log (fromInteger b)) /
                   log (fromInteger base))
 --WAS:           fromInt e * log (fromInteger b))
 
@@ -614,7 +619,7 @@ floatToDigits base x =
      let bk = expt base (-k) in
      gen [] (r * bk) s (mUp * bk) (mDn * bk)
  in
- (map toInt (reverse rds), k)
+ (map fromIntegral (reverse rds), k)
 
 \end{code}
 
@@ -763,6 +768,18 @@ minusFloat  (F# x) (F# y) = F# (minusFloat# x y)
 timesFloat  (F# x) (F# y) = F# (timesFloat# x y)
 divideFloat (F# x) (F# y) = F# (divideFloat# x y)
 
+{-# RULES
+"plusFloat x 0.0"   forall x#. plusFloat#  x#   0.0# = x#
+"plusFloat 0.0 x"   forall x#. plusFloat#  0.0# x#   = x#
+"minusFloat x 0.0"  forall x#. minusFloat# x#   0.0# = x#
+"minusFloat x x"    forall x#. minusFloat# x#   x#   = 0.0#
+"timesFloat x 0.0"  forall x#. timesFloat# x#   0.0# = 0.0#
+"timesFloat0.0 x"   forall x#. timesFloat# 0.0# x#   = 0.0#
+"timesFloat x 1.0"  forall x#. timesFloat# x#   1.0# = x#
+"timesFloat 1.0 x"  forall x#. timesFloat# 1.0# x#   = x#
+"divideFloat x 1.0" forall x#. divideFloat# x#  1.0# = x#
+  #-}
+
 negateFloat :: Float -> Float
 negateFloat (F# x)        = F# (negateFloat# x)
 
@@ -809,6 +826,18 @@ minusDouble  (D# x) (D# y) = D# (x -## y)
 timesDouble  (D# x) (D# y) = D# (x *## y)
 divideDouble (D# x) (D# y) = D# (x /## y)
 
+{-# RULES
+"plusDouble x 0.0"   forall x#. (+##) x#    0.0## = x#
+"plusDouble 0.0 x"   forall x#. (+##) 0.0## x#    = x#
+"minusDouble x 0.0"  forall x#. (-##) x#    0.0## = x#
+"minusDouble x x"    forall x#. (-##) x#    x#    = 0.0##
+"timesDouble x 0.0"  forall x#. (*##) x#    0.0## = 0.0##
+"timesDouble 0.0 x"  forall x#. (*##) 0.0## x#    = 0.0##
+"timesDouble x 1.0"  forall x#. (*##) x#    1.0## = x#
+"timesDouble 1.0 x"  forall x#. (*##) 1.0## x#    = x#
+"divideDouble x 1.0" forall x#. (/##) x#    1.0## = x#
+  #-}
+
 negateDouble :: Double -> Double
 negateDouble (D# x)        = D# (negateDouble# x)
 
@@ -876,3 +905,20 @@ foreign import ccall "isDoubleInfinite" unsafe isDoubleInfinite :: Double -> Int
 foreign import ccall "isDoubleDenormalized" unsafe isDoubleDenormalized :: Double -> Int
 foreign import ccall "isDoubleNegativeZero" unsafe isDoubleNegativeZero :: Double -> Int
 \end{code}
+
+%*********************************************************
+%*                                                     *
+\subsection{Coercion rules}
+%*                                                     *
+%*********************************************************
+
+\begin{code}
+{-# RULES
+"fromIntegral/Int->Float"   fromIntegral = int2Float
+"fromIntegral/Int->Double"  fromIntegral = int2Double
+"realToFrac/Float->Float"   realToFrac   = id :: Float -> Float
+"realToFrac/Float->Double"  realToFrac   = float2Double
+"realToFrac/Double->Float"  realToFrac   = double2Float
+"realToFrac/Double->Double" realToFrac   = id :: Double -> Double
+    #-}
+\end{code}