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