Typo
[packages/base.git] / Numeric.hs
1 {-# LANGUAGE Trustworthy #-}
2 {-# LANGUAGE NoImplicitPrelude, MagicHash #-}
3
4 -----------------------------------------------------------------------------
5 -- |
6 -- Module : Numeric
7 -- Copyright : (c) The University of Glasgow 2002
8 -- License : BSD-style (see the file libraries/base/LICENSE)
9 --
10 -- Maintainer : libraries@haskell.org
11 -- Stability : provisional
12 -- Portability : portable
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 -- * Showing
22
23 showSigned,
24
25 showIntAtBase,
26 showInt,
27 showHex,
28 showOct,
29
30 showEFloat,
31 showFFloat,
32 showGFloat,
33 showFFloatAlt,
34 showGFloatAlt,
35 showFloat,
36
37 floatToDigits,
38
39 -- * Reading
40
41 -- | /NB:/ 'readInt' is the \'dual\' of 'showIntAtBase',
42 -- and 'readDec' is the \`dual\' of 'showInt'.
43 -- The inconsistent naming is a historical accident.
44
45 readSigned,
46
47 readInt,
48 readDec,
49 readOct,
50 readHex,
51
52 readFloat,
53
54 lexDigits,
55
56 -- * Miscellaneous
57
58 fromRat,
59
60 ) where
61
62 import GHC.Base
63 import GHC.Read
64 import GHC.Real
65 import GHC.Float
66 import GHC.Num
67 import GHC.Show
68 import Data.Maybe
69 import Text.ParserCombinators.ReadP( ReadP, readP_to_S, pfail )
70 import qualified Text.Read.Lex as L
71
72 -- -----------------------------------------------------------------------------
73 -- Reading
74
75 -- | Reads an /unsigned/ 'Integral' value in an arbitrary base.
76 readInt :: Num a
77 => a -- ^ the base
78 -> (Char -> Bool) -- ^ a predicate distinguishing valid digits in this base
79 -> (Char -> Int) -- ^ a function converting a valid digit character to an 'Int'
80 -> ReadS a
81 readInt base isDigit valDigit = readP_to_S (L.readIntP base isDigit valDigit)
82
83 -- | Read an unsigned number in octal notation.
84 readOct :: (Eq a, Num a) => ReadS a
85 readOct = readP_to_S L.readOctP
86
87 -- | Read an unsigned number in decimal notation.
88 readDec :: (Eq a, Num a) => ReadS a
89 readDec = readP_to_S L.readDecP
90
91 -- | Read an unsigned number in hexadecimal notation.
92 -- Both upper or lower case letters are allowed.
93 readHex :: (Eq a, Num a) => ReadS a
94 readHex = readP_to_S L.readHexP
95
96 -- | Reads an /unsigned/ 'RealFrac' value,
97 -- expressed in decimal scientific notation.
98 readFloat :: RealFrac a => ReadS a
99 readFloat = readP_to_S readFloatP
100
101 readFloatP :: RealFrac a => ReadP a
102 readFloatP =
103 do tok <- L.lex
104 case tok of
105 L.Number n -> return $ fromRational $ L.numberToRational n
106 _ -> pfail
107
108 -- It's turgid to have readSigned work using list comprehensions,
109 -- but it's specified as a ReadS to ReadS transformer
110 -- With a bit of luck no one will use it.
111
112 -- | Reads a /signed/ 'Real' value, given a reader for an unsigned value.
113 readSigned :: (Real a) => ReadS a -> ReadS a
114 readSigned readPos = readParen False read'
115 where read' r = read'' r ++
116 (do
117 ("-",s) <- lex r
118 (x,t) <- read'' s
119 return (-x,t))
120 read'' r = do
121 (str,s) <- lex r
122 (n,"") <- readPos str
123 return (n,s)
124
125 -- -----------------------------------------------------------------------------
126 -- Showing
127
128 -- | Show /non-negative/ 'Integral' numbers in base 10.
129 showInt :: Integral a => a -> ShowS
130 showInt n0 cs0
131 | n0 < 0 = error "Numeric.showInt: can't show negative numbers"
132 | otherwise = go n0 cs0
133 where
134 go n cs
135 | n < 10 = case unsafeChr (ord '0' + fromIntegral n) of
136 c@(C# _) -> c:cs
137 | otherwise = case unsafeChr (ord '0' + fromIntegral r) of
138 c@(C# _) -> go q (c:cs)
139 where
140 (q,r) = n `quotRem` 10
141
142 -- Controlling the format and precision of floats. The code that
143 -- implements the formatting itself is in @PrelNum@ to avoid
144 -- mutual module deps.
145
146 {-# SPECIALIZE showEFloat ::
147 Maybe Int -> Float -> ShowS,
148 Maybe Int -> Double -> ShowS #-}
149 {-# SPECIALIZE showFFloat ::
150 Maybe Int -> Float -> ShowS,
151 Maybe Int -> Double -> ShowS #-}
152 {-# SPECIALIZE showGFloat ::
153 Maybe Int -> Float -> ShowS,
154 Maybe Int -> Double -> ShowS #-}
155
156 -- | Show a signed 'RealFloat' value
157 -- using scientific (exponential) notation (e.g. @2.45e2@, @1.5e-3@).
158 --
159 -- In the call @'showEFloat' digs val@, if @digs@ is 'Nothing',
160 -- the value is shown to full precision; if @digs@ is @'Just' d@,
161 -- then at most @d@ digits after the decimal point are shown.
162 showEFloat :: (RealFloat a) => Maybe Int -> a -> ShowS
163
164 -- | Show a signed 'RealFloat' value
165 -- using standard decimal notation (e.g. @245000@, @0.0015@).
166 --
167 -- In the call @'showFFloat' digs val@, if @digs@ is 'Nothing',
168 -- the value is shown to full precision; if @digs@ is @'Just' d@,
169 -- then at most @d@ digits after the decimal point are shown.
170 showFFloat :: (RealFloat a) => Maybe Int -> a -> ShowS
171
172 -- | Show a signed 'RealFloat' value
173 -- using standard decimal notation for arguments whose absolute value lies
174 -- between @0.1@ and @9,999,999@, and scientific notation otherwise.
175 --
176 -- In the call @'showGFloat' digs val@, if @digs@ is 'Nothing',
177 -- the value is shown to full precision; if @digs@ is @'Just' d@,
178 -- then at most @d@ digits after the decimal point are shown.
179 showGFloat :: (RealFloat a) => Maybe Int -> a -> ShowS
180
181 showEFloat d x = showString (formatRealFloat FFExponent d x)
182 showFFloat d x = showString (formatRealFloat FFFixed d x)
183 showGFloat d x = showString (formatRealFloat FFGeneric d x)
184
185 -- | Show a signed 'RealFloat' value
186 -- using standard decimal notation (e.g. @245000@, @0.0015@).
187 --
188 -- This behaves as 'showFFloat', except that a decimal point
189 -- is always guaranteed, even if not needed.
190 --
191 -- /Since: 4.7.0.0/
192 showFFloatAlt :: (RealFloat a) => Maybe Int -> a -> ShowS
193
194 -- | Show a signed 'RealFloat' value
195 -- using standard decimal notation for arguments whose absolute value lies
196 -- between @0.1@ and @9,999,999@, and scientific notation otherwise.
197 --
198 -- This behaves as 'showFFloat', except that a decimal point
199 -- is always guaranteed, even if not needed.
200 --
201 -- /Since: 4.7.0.0/
202 showGFloatAlt :: (RealFloat a) => Maybe Int -> a -> ShowS
203
204 showFFloatAlt d x = showString (formatRealFloatAlt FFFixed d True x)
205 showGFloatAlt d x = showString (formatRealFloatAlt FFGeneric d True x)
206
207 -- ---------------------------------------------------------------------------
208 -- Integer printing functions
209
210 -- | Shows a /non-negative/ 'Integral' number using the base specified by the
211 -- first argument, and the character representation specified by the second.
212 showIntAtBase :: (Integral a, Show a) => a -> (Int -> Char) -> a -> ShowS
213 showIntAtBase base toChr n0 r0
214 | base <= 1 = error ("Numeric.showIntAtBase: applied to unsupported base " ++ show base)
215 | n0 < 0 = error ("Numeric.showIntAtBase: applied to negative number " ++ show n0)
216 | otherwise = showIt (quotRem n0 base) r0
217 where
218 showIt (n,d) r = seq c $ -- stricter than necessary
219 case n of
220 0 -> r'
221 _ -> showIt (quotRem n base) r'
222 where
223 c = toChr (fromIntegral d)
224 r' = c : r
225
226 -- | Show /non-negative/ 'Integral' numbers in base 16.
227 showHex :: (Integral a,Show a) => a -> ShowS
228 showHex = showIntAtBase 16 intToDigit
229
230 -- | Show /non-negative/ 'Integral' numbers in base 8.
231 showOct :: (Integral a, Show a) => a -> ShowS
232 showOct = showIntAtBase 8 intToDigit