1 % -----------------------------------------------------------------------------
2 % $Id: Numeric.lhs,v 1.12 2001/02/22 16:48:24 qrczak Exp $
4 % (c) The University of Glasgow, 1997-2000
7 \section[Numeric]{Numeric interface}
9 Odds and ends, mostly functions for reading and showing
10 \tr{RealFloat}-like kind of values.
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
22 , readDec -- :: (Integral a) => ReadS a
23 , readOct -- :: (Integral a) => ReadS a
24 , readHex -- :: (Integral a) => ReadS a
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
33 , floatToDigits -- :: (RealFloat a) => Integer -> a -> ([Int], Int)
34 , lexDigits -- :: ReadS String
36 -- Implementation checked wrt. Haskell 98 lib report, 1/99.
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
50 import PrelNum ( ord_0 )
61 showInt :: Integral a => a -> ShowS
63 | i < 0 = error "Numeric.showInt: can't show negative numbers"
67 case quotRem n 10 of { (n', d) ->
68 case chr (ord_0 + fromIntegral d) of { C# c# -> -- stricter than necessary
72 if n' == 0 then r' else go n' r'
76 Controlling the format and precision of floats. The code that
77 implements the formatting itself is in @PrelNum@ to avoid
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 #-}
91 showEFloat :: (RealFloat a) => Maybe Int -> a -> ShowS
92 showFFloat :: (RealFloat a) => Maybe Int -> a -> ShowS
93 showGFloat :: (RealFloat a) => Maybe Int -> a -> ShowS
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)
103 %*********************************************************
105 All of this code is for Hugs only
106 GHC gets it from PrelFloat!
108 %*********************************************************
111 -- This converts a rational to a floating. This should be used in the
112 -- Fractional instances of Float and Double.
114 fromRat :: (RealFloat a) => Rational -> a
116 if x == 0 then encodeFloat 0 0 -- Handle exceptional cases
117 else if x < 0 then - fromRat' (-x) -- first.
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
129 where b = floatRadix 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'
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 =
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)
154 -- Exponentiation with a cache for the most common numbers.
157 expt :: Integer -> Int -> Integer
159 if base == 2 && n >= minExpt && n <= maxExpt then
164 expts :: Array Int Integer
165 expts = array (minExpt,maxExpt) [(n,2^n) | n <- [minExpt .. maxExpt]]
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
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
182 -- Misc utilities to show integers and floats
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
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
194 -- These are the format types. This type is not exported.
196 data FFFormat = FFExponent | FFFixed | FFGeneric
198 formatRealFloat :: (RealFloat a) => FFFormat -> Maybe Int -> a -> String
199 formatRealFloat fmt decs x = s
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))
208 doFmt fmt (floatToDigits (toInteger base) x)
210 let ds = map intToDigit is
213 doFmt (if e < 0 || e > 7 then FFExponent else FFFixed)
220 [d] -> d : ".0e" ++ show (e-1)
221 d:ds -> d : '.' : ds ++ 'e':show (e-1)
223 let dec' = max dec 1 in
225 [0] -> '0':'.':take dec' (repeat '0') ++ "e0"
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)
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
241 let dec' = max dec 0 in
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)
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')
254 roundTo :: Int -> Int -> [Int] -> (Int, [Int])
255 roundTo base d is = case f d is of
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, [])
262 let (c, ds) = f (d-1) is
264 in if i' == base then (1, 0:ds) else (0, i':ds)
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.
271 -- This function returns a list of digits (Ints in [0..base-1]) and an
274 floatToDigits :: (RealFloat a) => Integer -> a -> ([Int], Int)
276 floatToDigits _ 0 = ([0], 0)
277 floatToDigits base x =
278 let (f0, e0) = decodeFloat x
279 (minExp0, _) = floatRange 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)
292 (f*be*b*2, 2*b, be*b, b)
296 if e > minExp && f == b^(p-1) then
297 (f*b*2, b^(-e+1)*2, b, 1)
299 (f*2, b^(-e)*2, 1, 1)
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
309 ceiling ((log (fromInteger (f+1)) +
310 fromIntegral e * log (fromInteger b)) /
311 log (fromInteger base))
314 if r + mUp <= expt base n * s then n else fixup (n+1)
316 if expt base (-n) * (r + mUp) <= s then n
320 gen ds rn sN mUpN mDnN =
321 let (dn, rn') = (rn * base) `divMod` sN
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'
331 gen [] r (s * expt base k) mUp mDn
333 let bk = expt base (-k)
334 in gen [] (r * bk) s (mUp * bk) (mDn * bk)
335 in (map fromIntegral (reverse rds), k)