author simonpj Tue, 18 Jun 2002 09:31:06 +0000 (09:31 +0000) committer simonpj 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 patch | blob | history GHC/Real.lhs patch | blob | history Text/Read/Lex.hs patch | blob | history

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
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]