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