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