1 {-# LANGUAGE CPP, NoImplicitPrelude, MagicHash #-}
3 -----------------------------------------------------------------------------
6 -- Copyright : (c) The University of Glasgow 2002
7 -- License : BSD-style (see the file libraries/base/LICENSE)
9 -- Maintainer : libraries@haskell.org
10 -- Stability : provisional
11 -- Portability : portable
13 -- Odds and ends, mostly functions for reading and showing
14 -- 'RealFloat'-like kind of values.
16 -----------------------------------------------------------------------------
22 showSigned, -- :: (Real a) => (a -> ShowS) -> Int -> a -> ShowS
24 showIntAtBase, -- :: Integral a => a -> (a -> Char) -> a -> ShowS
25 showInt, -- :: Integral a => a -> ShowS
26 showHex, -- :: Integral a => a -> ShowS
27 showOct, -- :: Integral a => a -> ShowS
29 showEFloat, -- :: (RealFloat a) => Maybe Int -> a -> ShowS
30 showFFloat, -- :: (RealFloat a) => Maybe Int -> a -> ShowS
31 showGFloat, -- :: (RealFloat a) => Maybe Int -> a -> ShowS
32 showFloat, -- :: (RealFloat a) => a -> ShowS
34 floatToDigits, -- :: (RealFloat a) => Integer -> a -> ([Int], Int)
38 -- | /NB:/ 'readInt' is the \'dual\' of 'showIntAtBase',
39 -- and 'readDec' is the \`dual\' of 'showInt'.
40 -- The inconsistent naming is a historical accident.
42 readSigned, -- :: (Real a) => ReadS a -> ReadS a
44 readInt, -- :: (Integral a) => a -> (Char -> Bool)
45 -- -> (Char -> Int) -> ReadS a
46 readDec, -- :: (Integral a) => ReadS a
47 readOct, -- :: (Integral a) => ReadS a
48 readHex, -- :: (Integral a) => ReadS a
50 readFloat, -- :: (RealFloat a) => ReadS a
52 lexDigits, -- :: ReadS String
56 fromRat, -- :: (RealFloat a) => Rational -> a
60 #ifdef __GLASGOW_HASKELL__
68 import Text.ParserCombinators.ReadP( ReadP, readP_to_S, pfail )
69 import qualified Text.Read.Lex as L
79 #ifdef __GLASGOW_HASKELL__
80 -- -----------------------------------------------------------------------------
83 -- | Reads an /unsigned/ 'Integral' value in an arbitrary base.
86 -> (Char -> Bool) -- ^ a predicate distinguishing valid digits in this base
87 -> (Char -> Int) -- ^ a function converting a valid digit character to an 'Int'
89 readInt base isDigit valDigit = readP_to_S (L.readIntP base isDigit valDigit)
91 -- | Read an unsigned number in octal notation.
92 readOct :: Num a => ReadS a
93 readOct = readP_to_S L.readOctP
95 -- | Read an unsigned number in decimal notation.
96 readDec :: Num a => ReadS a
97 readDec = readP_to_S L.readDecP
99 -- | Read an unsigned number in hexadecimal notation.
100 -- Both upper or lower case letters are allowed.
101 readHex :: Num a => ReadS a
102 readHex = readP_to_S L.readHexP
104 -- | Reads an /unsigned/ 'RealFrac' value,
105 -- expressed in decimal scientific notation.
106 readFloat :: RealFrac a => ReadS a
107 readFloat = readP_to_S readFloatP
109 readFloatP :: RealFrac a => ReadP a
113 L.Rat y -> return (fromRational y)
114 L.Int i -> return (fromInteger i)
117 -- It's turgid to have readSigned work using list comprehensions,
118 -- but it's specified as a ReadS to ReadS transformer
119 -- With a bit of luck no one will use it.
121 -- | Reads a /signed/ 'Real' value, given a reader for an unsigned value.
122 readSigned :: (Real a) => ReadS a -> ReadS a
123 readSigned readPos = readParen False read'
124 where read' r = read'' r ++
131 (n,"") <- readPos str
134 -- -----------------------------------------------------------------------------
137 -- | Show /non-negative/ 'Integral' numbers in base 10.
138 showInt :: Integral a => a -> ShowS
140 | n0 < 0 = error "Numeric.showInt: can't show negative numbers"
141 | otherwise = go n0 cs0
144 | n < 10 = case unsafeChr (ord '0' + fromIntegral n) of
146 | otherwise = case unsafeChr (ord '0' + fromIntegral r) of
147 c@(C# _) -> go q (c:cs)
149 (q,r) = n `quotRem` 10
151 -- Controlling the format and precision of floats. The code that
152 -- implements the formatting itself is in @PrelNum@ to avoid
153 -- mutual module deps.
155 {-# SPECIALIZE showEFloat ::
156 Maybe Int -> Float -> ShowS,
157 Maybe Int -> Double -> ShowS #-}
158 {-# SPECIALIZE showFFloat ::
159 Maybe Int -> Float -> ShowS,
160 Maybe Int -> Double -> ShowS #-}
161 {-# SPECIALIZE showGFloat ::
162 Maybe Int -> Float -> ShowS,
163 Maybe Int -> Double -> ShowS #-}
165 -- | Show a signed 'RealFloat' value
166 -- using scientific (exponential) notation (e.g. @2.45e2@, @1.5e-3@).
168 -- In the call @'showEFloat' digs val@, if @digs@ is 'Nothing',
169 -- the value is shown to full precision; if @digs@ is @'Just' d@,
170 -- then at most @d@ digits after the decimal point are shown.
171 showEFloat :: (RealFloat a) => Maybe Int -> a -> ShowS
173 -- | Show a signed 'RealFloat' value
174 -- using standard decimal notation (e.g. @245000@, @0.0015@).
176 -- In the call @'showFFloat' 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 showFFloat :: (RealFloat a) => Maybe Int -> a -> ShowS
181 -- | Show a signed 'RealFloat' value
182 -- using standard decimal notation for arguments whose absolute value lies
183 -- between @0.1@ and @9,999,999@, and scientific notation otherwise.
185 -- In the call @'showGFloat' digs val@, if @digs@ is 'Nothing',
186 -- the value is shown to full precision; if @digs@ is @'Just' d@,
187 -- then at most @d@ digits after the decimal point are shown.
188 showGFloat :: (RealFloat a) => Maybe Int -> a -> ShowS
190 showEFloat d x = showString (formatRealFloat FFExponent d x)
191 showFFloat d x = showString (formatRealFloat FFFixed d x)
192 showGFloat d x = showString (formatRealFloat FFGeneric d x)
193 #endif /* __GLASGOW_HASKELL__ */
195 -- ---------------------------------------------------------------------------
196 -- Integer printing functions
198 -- | Shows a /non-negative/ 'Integral' number using the base specified by the
199 -- first argument, and the character representation specified by the second.
200 showIntAtBase :: Integral a => a -> (Int -> Char) -> a -> ShowS
201 showIntAtBase base toChr n0 r0
202 | base <= 1 = error ("Numeric.showIntAtBase: applied to unsupported base " ++ show base)
203 | n0 < 0 = error ("Numeric.showIntAtBase: applied to negative number " ++ show n0)
204 | otherwise = showIt (quotRem n0 base) r0
206 showIt (n,d) r = seq c $ -- stricter than necessary
209 _ -> showIt (quotRem n base) r'
211 c = toChr (fromIntegral d)
214 -- | Show /non-negative/ 'Integral' numbers in base 16.
215 showHex :: Integral a => a -> ShowS
216 showHex = showIntAtBase 16 intToDigit
218 -- | Show /non-negative/ 'Integral' numbers in base 8.
219 showOct :: Integral a => a -> ShowS
220 showOct = showIntAtBase 8 intToDigit