[project @ 2002-04-11 12:03:43 by simonpj]
[ghc-base.git] / Numeric.hs
1 {-# OPTIONS -fno-implicit-prelude #-}
2 -----------------------------------------------------------------------------
3 -- 
4 -- Module      :  Numeric
5 -- Copyright   :  (c) The University of Glasgow 2002
6 -- License     :  BSD-style (see the file libraries/core/LICENSE)
7 -- 
8 -- Maintainer  :  libraries@haskell.org
9 -- Stability   :  provisional
10 -- Portability :  portable
11 --
12 -- $Id: Numeric.hs,v 1.6 2002/04/11 12:03:43 simonpj Exp $
13 --
14 -- Odds and ends, mostly functions for reading and showing
15 -- RealFloat-like kind of values.
16 --
17 -----------------------------------------------------------------------------
18
19 module Numeric (
20
21         fromRat,          -- :: (RealFloat a) => Rational -> a
22         showSigned,       -- :: (Real a) => (a -> ShowS) -> Int -> a -> ShowS
23         readSigned,       -- :: (Real a) => ReadS a -> ReadS a
24
25         readInt,          -- :: (Integral a) => a -> (Char -> Bool)
26                           --         -> (Char -> Int) -> ReadS a
27         readDec,          -- :: (Integral a) => ReadS a
28         readOct,          -- :: (Integral a) => ReadS a
29         readHex,          -- :: (Integral a) => ReadS a
30
31         showInt,          -- :: Integral a => a -> ShowS
32         showIntAtBase,    -- :: Integral a => a -> (a -> Char) -> a -> ShowS
33         showHex,          -- :: Integral a => a -> ShowS
34         showOct,          -- :: Integral a => a -> ShowS
35         showBin,          -- :: Integral a => a -> ShowS
36
37         showEFloat,       -- :: (RealFloat a) => Maybe Int -> a -> ShowS
38         showFFloat,       -- :: (RealFloat a) => Maybe Int -> a -> ShowS
39         showGFloat,       -- :: (RealFloat a) => Maybe Int -> a -> ShowS
40         showFloat,        -- :: (RealFloat a) => a -> ShowS
41         readFloat,        -- :: (RealFloat a) => ReadS a
42         
43         floatToDigits,    -- :: (RealFloat a) => Integer -> a -> ([Int], Int)
44         lexDigits,        -- :: ReadS String
45
46         ) where
47
48 import Data.Char
49
50 #ifdef __GLASGOW_HASKELL__
51 import GHC.Base
52 import GHC.Read
53 import GHC.Real
54 import GHC.Float
55 import GHC.Num
56 import GHC.Show
57 import Data.Maybe
58 import Text.ParserCombinators.ReadP( ReadP, readP_to_S, pfail )
59 import qualified Text.Read.Lex as L
60 #endif
61
62 #ifdef __HUGS__
63 import Array
64 #endif
65
66
67 -- *********************************************************
68 -- *                                                       *
69 -- \subsection{Reading}
70 -- *                                                       *
71 -- *********************************************************
72
73 readInt :: Num a => a -> (Char -> Bool) -> (Char -> Int) -> ReadS a
74 readInt base isDigit valDigit = readP_to_S (L.readIntP base isDigit valDigit)
75
76 readOct, readDec, readHex :: Num a => ReadS a
77 readOct = readP_to_S L.readOctP
78 readDec = readP_to_S L.readDecP
79 readHex = readP_to_S L.readHexP 
80
81 readFloat :: RealFrac a => ReadS a
82 readFloat = readP_to_S readFloatP
83
84 readFloatP :: RealFrac a => ReadP a
85 readFloatP =
86   do L.Number x <- L.lex
87      case L.numberToRational x of
88        Nothing -> pfail
89        Just y  -> return (fromRational y)
90
91 -- It's turgid to have readSigned work using list comprehensions,
92 -- but it's specified as a ReadS to ReadS transformer
93 -- With a bit of luck no one will use it.
94 readSigned :: (Real a) => ReadS a -> ReadS a
95 readSigned readPos = readParen False read'
96                      where read' r  = read'' r ++
97                                       (do
98                                         ("-",s) <- lex r
99                                         (x,t)   <- read'' s
100                                         return (-x,t))
101                            read'' r = do
102                                (str,s) <- lex r
103                                (n,"")  <- readPos str
104                                return (n,s)
105
106
107 -- *********************************************************
108 -- *                                                       *
109 -- \subsection{Showing}
110 -- *                                                       *
111 -- *********************************************************
112
113
114
115 #ifdef __GLASGOW_HASKELL__
116 showInt :: Integral a => a -> ShowS
117 showInt n cs
118     | n < 0     = error "Numeric.showInt: can't show negative numbers"
119     | otherwise = go n cs
120     where
121     go n cs
122         | n < 10    = case unsafeChr (ord '0' + fromIntegral n) of
123             c@(C# _) -> c:cs
124         | otherwise = case unsafeChr (ord '0' + fromIntegral r) of
125             c@(C# _) -> go q (c:cs)
126         where
127         (q,r) = n `quotRem` 10
128
129 -- Controlling the format and precision of floats. The code that
130 -- implements the formatting itself is in @PrelNum@ to avoid
131 -- mutual module deps.
132
133 {-# SPECIALIZE showEFloat ::
134         Maybe Int -> Float  -> ShowS,
135         Maybe Int -> Double -> ShowS #-}
136 {-# SPECIALIZE showFFloat ::
137         Maybe Int -> Float  -> ShowS,
138         Maybe Int -> Double -> ShowS #-}
139 {-# SPECIALIZE showGFloat ::
140         Maybe Int -> Float  -> ShowS,
141         Maybe Int -> Double -> ShowS #-}
142
143 showEFloat    :: (RealFloat a) => Maybe Int -> a -> ShowS
144 showFFloat    :: (RealFloat a) => Maybe Int -> a -> ShowS
145 showGFloat    :: (RealFloat a) => Maybe Int -> a -> ShowS
146
147 showEFloat d x =  showString (formatRealFloat FFExponent d x)
148 showFFloat d x =  showString (formatRealFloat FFFixed d x)
149 showGFloat d x =  showString (formatRealFloat FFGeneric d x)
150 #endif
151
152 #ifdef __HUGS__
153 -- This converts a rational to a floating.  This should be used in the
154 -- Fractional instances of Float and Double.
155
156 fromRat :: (RealFloat a) => Rational -> a
157 fromRat x = 
158     if x == 0 then encodeFloat 0 0              -- Handle exceptional cases
159     else if x < 0 then - fromRat' (-x)          -- first.
160     else fromRat' x
161
162 -- Conversion process:
163 -- Scale the rational number by the RealFloat base until
164 -- it lies in the range of the mantissa (as used by decodeFloat/encodeFloat).
165 -- Then round the rational to an Integer and encode it with the exponent
166 -- that we got from the scaling.
167 -- To speed up the scaling process we compute the log2 of the number to get
168 -- a first guess of the exponent.
169 fromRat' :: (RealFloat a) => Rational -> a
170 fromRat' x = r
171   where b = floatRadix r
172         p = floatDigits r
173         (minExp0, _) = floatRange r
174         minExp = minExp0 - p            -- the real minimum exponent
175         xMin = toRational (expt b (p-1))
176         xMax = toRational (expt b p)
177         p0 = (integerLogBase b (numerator x) -
178               integerLogBase b (denominator x) - p) `max` minExp
179         f = if p0 < 0 then 1 % expt b (-p0) else expt b p0 % 1
180         (x', p') = scaleRat (toRational b) minExp xMin xMax p0 (x / f)
181         r = encodeFloat (round x') p'
182
183 -- Scale x until xMin <= x < xMax, or p (the exponent) <= minExp.
184 scaleRat :: Rational -> Int -> Rational -> Rational -> 
185              Int -> Rational -> (Rational, Int)
186 scaleRat b minExp xMin xMax p x =
187     if p <= minExp then
188         (x, p)
189     else if x >= xMax then
190         scaleRat b minExp xMin xMax (p+1) (x/b)
191     else if x < xMin  then
192         scaleRat b minExp xMin xMax (p-1) (x*b)
193     else
194         (x, p)
195
196 -- Exponentiation with a cache for the most common numbers.
197 minExpt = 0::Int
198 maxExpt = 1100::Int
199 expt :: Integer -> Int -> Integer
200 expt base n =
201     if base == 2 && n >= minExpt && n <= maxExpt then
202         expts!n
203     else
204         base^n
205
206 expts :: Array Int Integer
207 expts = array (minExpt,maxExpt) [(n,2^n) | n <- [minExpt .. maxExpt]]
208
209 -- Compute the (floor of the) log of i in base b.
210 -- Simplest way would be just divide i by b until it's smaller then b,
211 -- but that would be very slow!  We are just slightly more clever.
212 integerLogBase :: Integer -> Integer -> Int
213 integerLogBase b i =
214      if i < b then
215         0
216      else
217         -- Try squaring the base first to cut down the number of divisions.
218         let l = 2 * integerLogBase (b*b) i
219             doDiv :: Integer -> Int -> Int
220             doDiv i l = if i < b then l else doDiv (i `div` b) (l+1)
221         in  doDiv (i `div` (b^l)) l
222
223
224 -- Misc utilities to show integers and floats 
225
226 showEFloat     :: (RealFloat a) => Maybe Int -> a -> ShowS
227 showFFloat     :: (RealFloat a) => Maybe Int -> a -> ShowS
228 showGFloat     :: (RealFloat a) => Maybe Int -> a -> ShowS
229 showFloat      :: (RealFloat a) => a -> ShowS
230
231 showEFloat d x =  showString (formatRealFloat FFExponent d x)
232 showFFloat d x =  showString (formatRealFloat FFFixed d x)
233 showGFloat d x =  showString (formatRealFloat FFGeneric d x)
234 showFloat      =  showGFloat Nothing 
235
236 -- These are the format types.  This type is not exported.
237
238 data FFFormat = FFExponent | FFFixed | FFGeneric
239
240 formatRealFloat :: (RealFloat a) => FFFormat -> Maybe Int -> a -> String
241 formatRealFloat fmt decs x = s
242   where base = 10
243         s = if isNaN x then 
244                 "NaN"
245             else if isInfinite x then 
246                 if x < 0 then "-Infinity" else "Infinity"
247             else if x < 0 || isNegativeZero x then 
248                 '-' : doFmt fmt (floatToDigits (toInteger base) (-x))
249             else 
250                 doFmt fmt (floatToDigits (toInteger base) x)
251         doFmt fmt (is, e) =
252             let ds = map intToDigit is
253             in  case fmt of
254                 FFGeneric -> 
255                     doFmt (if e < 0 || e > 7 then FFExponent else FFFixed)
256                           (is, e)
257                 FFExponent ->
258                     case decs of
259                     Nothing ->
260                         case ds of
261                          ['0'] -> "0.0e0"
262                          [d]   -> d : ".0e" ++ show (e-1)
263                          d:ds  -> d : '.' : ds ++ 'e':show (e-1)
264                     Just dec ->
265                         let dec' = max dec 1 in
266                         case is of
267                          [0] -> '0':'.':take dec' (repeat '0') ++ "e0"
268                          _ ->
269                           let (ei, is') = roundTo base (dec'+1) is
270                               d:ds = map intToDigit
271                                          (if ei > 0 then init is' else is')
272                           in d:'.':ds  ++ "e" ++ show (e-1+ei)
273                 FFFixed ->
274                     case decs of
275                     Nothing ->
276                         let f 0 s ds = mk0 s ++ "." ++ mk0 ds
277                             f n s "" = f (n-1) (s++"0") ""
278                             f n s (d:ds) = f (n-1) (s++[d]) ds
279                             mk0 "" = "0"
280                             mk0 s = s
281                         in  f e "" ds
282                     Just dec ->
283                         let dec' = max dec 0 in
284                         if e >= 0 then
285                             let (ei, is') = roundTo base (dec' + e) is
286                                 (ls, rs) = splitAt (e+ei) (map intToDigit is')
287                             in  (if null ls then "0" else ls) ++ 
288                                 (if null rs then "" else '.' : rs)
289                         else
290                             let (ei, is') = roundTo base dec'
291                                               (replicate (-e) 0 ++ is)
292                                 d : ds = map intToDigit
293                                             (if ei > 0 then is' else 0:is')
294                             in  d : '.' : ds
295
296 roundTo :: Int -> Int -> [Int] -> (Int, [Int])
297 roundTo base d is = case f d is of
298                 (0, is) -> (0, is)
299                 (1, is) -> (1, 1 : is)
300   where b2 = base `div` 2
301         f n [] = (0, replicate n 0)
302         f 0 (i:_) = (if i >= b2 then 1 else 0, [])
303         f d (i:is) = 
304             let (c, ds) = f (d-1) is
305                 i' = c + i
306             in  if i' == base then (1, 0:ds) else (0, i':ds)
307
308 --
309 -- Based on "Printing Floating-Point Numbers Quickly and Accurately"
310 -- by R.G. Burger and R. K. Dybvig, in PLDI 96.
311 -- This version uses a much slower logarithm estimator.  It should be improved.
312
313 -- This function returns a list of digits (Ints in [0..base-1]) and an
314 -- exponent.
315
316 floatToDigits :: (RealFloat a) => Integer -> a -> ([Int], Int)
317
318 floatToDigits _ 0 = ([0], 0)
319 floatToDigits base x =
320     let (f0, e0) = decodeFloat x
321         (minExp0, _) = floatRange x
322         p = floatDigits x
323         b = floatRadix x
324         minExp = minExp0 - p            -- the real minimum exponent
325         -- Haskell requires that f be adjusted so denormalized numbers
326         -- will have an impossibly low exponent.  Adjust for this.
327         (f, e) = let n = minExp - e0
328                  in  if n > 0 then (f0 `div` (b^n), e0+n) else (f0, e0)
329
330         (r, s, mUp, mDn) =
331            if e >= 0 then
332                let be = b^e in
333                if f == b^(p-1) then
334                    (f*be*b*2, 2*b, be*b, b)
335                else
336                    (f*be*2, 2, be, be)
337            else
338                if e > minExp && f == b^(p-1) then
339                    (f*b*2, b^(-e+1)*2, b, 1)
340                else
341                    (f*2, b^(-e)*2, 1, 1)
342         k = 
343             let k0 =
344                     if b==2 && base==10 then
345                         -- logBase 10 2 is slightly bigger than 3/10 so
346                         -- the following will err on the low side.  Ignoring
347                         -- the fraction will make it err even more.
348                         -- Haskell promises that p-1 <= logBase b f < p.
349                         (p - 1 + e0) * 3 `div` 10
350                     else
351                         ceiling ((log (fromInteger (f+1)) + 
352                                  fromIntegral e * log (fromInteger b)) / 
353                                   log (fromInteger base))
354                 fixup n =
355                     if n >= 0 then
356                         if r + mUp <= expt base n * s then n else fixup (n+1)
357                     else
358                         if expt base (-n) * (r + mUp) <= s then n
359                                                            else fixup (n+1)
360             in  fixup k0
361
362         gen ds rn sN mUpN mDnN =
363             let (dn, rn') = (rn * base) `divMod` sN
364                 mUpN' = mUpN * base
365                 mDnN' = mDnN * base
366             in  case (rn' < mDnN', rn' + mUpN' > sN) of
367                 (True,  False) -> dn : ds
368                 (False, True)  -> dn+1 : ds
369                 (True,  True)  -> if rn' * 2 < sN then dn : ds else dn+1 : ds
370                 (False, False) -> gen (dn:ds) rn' sN mUpN' mDnN'
371         rds =
372             if k >= 0 then
373                 gen [] r (s * expt base k) mUp mDn
374             else
375                 let bk = expt base (-k)
376                 in  gen [] (r * bk) s (mUp * bk) (mDn * bk)
377     in  (map fromIntegral (reverse rds), k)
378 #endif
379
380 -- ---------------------------------------------------------------------------
381 -- Integer printing functions
382
383 showIntAtBase :: Integral a => a -> (a -> Char) -> a -> ShowS
384 showIntAtBase base toChr n r
385   | n < 0  = error ("Numeric.showIntAtBase: applied to negative number " ++ show n)
386   | otherwise = 
387     case quotRem n base of { (n', d) ->
388     let c = toChr d in
389     seq c $ -- stricter than necessary
390     let
391         r' = c : r
392     in
393     if n' == 0 then r' else showIntAtBase base toChr n' r'
394     }
395
396 showHex :: Integral a => a -> ShowS
397 showHex n r = 
398  showString "0x" $
399  showIntAtBase 16 (toChrHex) n r
400  where  
401   toChrHex d
402     | d < 10    = chr (ord '0' + fromIntegral d)
403     | otherwise = chr (ord 'a' + fromIntegral (d - 10))
404
405 showOct :: Integral a => a -> ShowS
406 showOct n r = 
407  showString "0o" $
408  showIntAtBase 8 (toChrOct) n r
409  where toChrOct d = chr (ord '0' + fromIntegral d)
410
411 showBin :: Integral a => a -> ShowS
412 showBin n r = 
413  showString "0b" $
414  showIntAtBase 2 (toChrOct) n r
415  where toChrOct d = chr (ord '0' + fromIntegral d)