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