[project @ 2002-06-18 09:31:05 by simonpj]
authorsimonpj <unknown>
Tue, 18 Jun 2002 09:31:06 +0000 (09:31 +0000)
committersimonpj <unknown>
Tue, 18 Jun 2002 09:31:06 +0000 (09:31 +0000)
--------------------------
Deal with NaN and Infinity
--------------------------

This commit arranges that

* GHC.Real exports infinity   :: Rational = 1 :% 0
notANumber :: Rational = 0 :% 0

* GHC.Float.fromRat converts these Rational non-numbers into
  their Float/Double equivalents

As a result, arith015/arith016 start to work again.  We can
read NaN and Infinity into Float/Double.

GHC/Float.lhs
GHC/Real.lhs
Text/Read/Lex.hs

index 382ef64..5c68de4 100644 (file)
@@ -675,14 +675,18 @@ fromRat x = x'
 Now, here's Lennart's code (which works)
 
 \begin{code}
-{-# SPECIALISE fromRat :: 
-       Rational -> Double,
-       Rational -> Float #-}
+{-# SPECIALISE fromRat :: Rational -> Double,
+                         Rational -> Float #-}
 fromRat :: (RealFloat a) => Rational -> a
-fromRat x 
-  | x == 0    =  encodeFloat 0 0               -- Handle exceptional cases
-  | x <  0    =  - fromRat' (-x)               -- first.
-  | otherwise =  fromRat' x
+
+-- Deal with special cases first, delegating the real work to fromRat'
+fromRat (n :% 0) | n > 0  =  1/0       -- +Infinity
+                | n == 0 =  0/0        -- NaN
+                | n < 0  = -1/0        -- -Infinity
+
+fromRat (n :% d) | n > 0  = fromRat' (n :% d)
+                | n == 0 = encodeFloat 0 0             -- Zero
+                | n < 0  = - fromRat' ((-n) :% d)
 
 -- Conversion process:
 -- Scale the rational number by the RealFloat base until
@@ -693,6 +697,7 @@ fromRat x
 -- a first guess of the exponent.
 
 fromRat' :: (RealFloat a) => Rational -> a
+-- Invariant: argument is strictly positive
 fromRat' x = r
   where b = floatRadix r
         p = floatDigits r
index 13be142..be30073 100644 (file)
@@ -41,6 +41,13 @@ default ()           -- Double isn't available yet,
 \begin{code}
 data  (Integral a)     => Ratio a = !a :% !a  deriving (Eq)
 type  Rational         =  Ratio Integer
+
+infinity, notANumber :: Rational
+infinity   = 1 :% 0
+notANumber = 0 :% 0
+
+-- Use :%, not % for Inf/NaN; the latter would 
+-- immediately lead to a runtime error, because it normalises. 
 \end{code}
 
 
index f2c0469..01ca6ac 100644 (file)
@@ -36,7 +36,7 @@ import GHC.Show( Show(.. ), showChar, showString,
                 isSpace, isAlpha, isAlphaNum,
                 isOctDigit, isHexDigit, toUpper )
 import GHC.Real( Ratio(..), Integral, Rational, (%), fromIntegral, fromRational, 
-                toInteger, (^), (^^) )
+                toInteger, (^), (^^), infinity, notANumber )
 import GHC.Float( Float, Double )
 import GHC.List
 import GHC.Show( ShowS, shows )
@@ -284,21 +284,6 @@ lexString =
 -- ---------------------------------------------------------------------------
 --  Lexing numbers
 
-infinity, notANumber :: Rational
-infinity   = 1 :% 0
-notANumber = 0 :% 0
-
--- Use :%, not % for Inf/NaN, the latter would 
--- immediately lead to a runtime error. 
---
--- Note that
---     isInfinite (read "Infinity" :: Float)
---  or
---     isInfinite (fromRational (1 :% 0))
--- still don't work, because fromRational is not OK for those cases.
--- 
--- The whole Infinity/NaN story is a bit murky to me
-
 type Base   = Int
 type Digits = [Int]