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