{-# LANGUAGE Trustworthy #-}{-# LANGUAGE NoImplicitPrelude, MagicHash #-}------------------------------------------------------------------------------- |-- Module : Numeric-- Copyright : (c) The University of Glasgow 2002-- License : BSD-style (see the file libraries/base/LICENSE)---- Maintainer : libraries@haskell.org-- Stability : provisional-- Portability : portable---- Odds and ends, mostly functions for reading and showing-- 'RealFloat'-like kind of values.-------------------------------------------------------------------------------moduleNumeric(-- * ShowingshowSigned ,showIntAtBase ,showInt ,showBin ,showHex ,showOct ,showEFloat ,showFFloat ,showGFloat ,showFFloatAlt ,showGFloatAlt ,showFloat ,showHFloat ,floatToDigits ,-- * Reading-- | /NB:/ 'readInt' is the \'dual\' of 'showIntAtBase',-- and 'readDec' is the \`dual\' of 'showInt'.-- The inconsistent naming is a historical accident.readSigned ,readInt ,readBin ,readDec ,readOct ,readHex ,readFloat ,lexDigits ,-- * MiscellaneousfromRat ,Floating (..))whereimportGHC.Base importGHC.Read importGHC.Real importGHC.Float importGHC.Num importGHC.Show importText.ParserCombinators.ReadP (ReadP ,readP_to_S ,pfail )importqualifiedText.Read.Lex asL-- $setup-- >>> import Prelude-- ------------------------------------------------------------------------------- Reading-- | Reads an /unsigned/ integral value in an arbitrary base.readInt ::Num a =>a -- ^ the base->(Char ->Bool )-- ^ a predicate distinguishing valid digits in this base->(Char ->Int )-- ^ a function converting a valid digit character to an 'Int'->ReadS a readInt :: forall a. Num a => a -> (Char -> Bool) -> (Char -> Int) -> ReadS a readInt a base Char -> Bool isDigit Char -> Int valDigit =ReadP a -> ReadS a forall a. ReadP a -> ReadS a readP_to_S (a -> (Char -> Bool) -> (Char -> Int) -> ReadP a forall a. Num a => a -> (Char -> Bool) -> (Char -> Int) -> ReadP a L.readIntP a base Char -> Bool isDigit Char -> Int valDigit )-- | Read an unsigned number in binary notation.---- >>> readBin "10011"-- [(19,"")]readBin ::(Eq a ,Num a )=>ReadS a readBin :: forall a. (Eq a, Num a) => ReadS a readBin =ReadP a -> ReadS a forall a. ReadP a -> ReadS a readP_to_S ReadP a forall a. (Eq a, Num a) => ReadP a L.readBinP -- | Read an unsigned number in octal notation.---- >>> readOct "0644"-- [(420,"")]readOct ::(Eq a ,Num a )=>ReadS a readOct :: forall a. (Eq a, Num a) => ReadS a readOct =ReadP a -> ReadS a forall a. ReadP a -> ReadS a readP_to_S ReadP a forall a. (Eq a, Num a) => ReadP a L.readOctP -- | Read an unsigned number in decimal notation.---- >>> readDec "0644"-- [(644,"")]readDec ::(Eq a ,Num a )=>ReadS a readDec :: forall a. (Eq a, Num a) => ReadS a readDec =ReadP a -> ReadS a forall a. ReadP a -> ReadS a readP_to_S ReadP a forall a. (Eq a, Num a) => ReadP a L.readDecP -- | Read an unsigned number in hexadecimal notation.-- Both upper or lower case letters are allowed.---- >>> readHex "deadbeef"-- [(3735928559,"")]readHex ::(Eq a ,Num a )=>ReadS a readHex :: forall a. (Eq a, Num a) => ReadS a readHex =ReadP a -> ReadS a forall a. ReadP a -> ReadS a readP_to_S ReadP a forall a. (Eq a, Num a) => ReadP a L.readHexP -- | Reads an /unsigned/ 'RealFrac' value,-- expressed in decimal scientific notation.---- Note that this function takes time linear in the magnitude of its input-- which can scale exponentially with input size (e.g. @"1e100000000"@ is a-- very large number while having a very small textual form).-- For this reason, users should take care to avoid using this function on-- untrusted input. Users needing to parse floating point values-- (e.g. 'Float') are encouraged to instead use 'read', which does-- not suffer from this issue.readFloat ::RealFrac a =>ReadS a readFloat :: forall a. RealFrac a => ReadS a readFloat =ReadP a -> ReadS a forall a. ReadP a -> ReadS a readP_to_S ReadP a forall a. RealFrac a => ReadP a readFloatP readFloatP ::RealFrac a =>ReadP a readFloatP :: forall a. RealFrac a => ReadP a readFloatP =doLexeme tok <-ReadP Lexeme L.lex caseLexeme tok ofL.Number Number n ->a -> ReadP a forall a. a -> ReadP a forall (m :: * -> *) a. Monad m => a -> m a return (a -> ReadP a) -> a -> ReadP a forall a b. (a -> b) -> a -> b $ Rational -> a forall a. Fractional a => Rational -> a fromRational (Rational -> a) -> Rational -> a forall a b. (a -> b) -> a -> b $ Number -> Rational L.numberToRational Number n Lexeme _->ReadP a forall a. ReadP a pfail -- It's turgid to have readSigned work using list comprehensions,-- but it's specified as a ReadS to ReadS transformer-- With a bit of luck no one will use it.-- | Reads a /signed/ 'Real' value, given a reader for an unsigned value.readSigned ::(Real a )=>ReadS a ->ReadS a readSigned :: forall a. Real a => ReadS a -> ReadS a readSigned ReadS a readPos =Bool -> ReadS a -> ReadS a forall a. Bool -> ReadS a -> ReadS a readParen Bool False ReadS a read' whereread' :: ReadS a read' String r =ReadS a read'' String r [(a, String)] -> [(a, String)] -> [(a, String)] forall a. [a] -> [a] -> [a] ++ (do(String "-",String s )<-ReadS String lex String r (a x ,String t )<-ReadS a read'' String s (a, String) -> [(a, String)] forall a. a -> [a] forall (m :: * -> *) a. Monad m => a -> m a return (-a x ,String t ))read'' :: ReadS a read'' String r =do(String str ,String s )<-ReadS String lex String r (a n ,String "")<-ReadS a readPos String str (a, String) -> [(a, String)] forall a. a -> [a] forall (m :: * -> *) a. Monad m => a -> m a return (a n ,String s )-- ------------------------------------------------------------------------------- Showing-- | Show /non-negative/ 'Integral' numbers in base 10.showInt ::Integral a =>a ->ShowS showInt :: forall a. Integral a => a -> ShowS showInt a n0 String cs0 |a n0 a -> a -> Bool forall a. Ord a => a -> a -> Bool < a 0=ShowS forall a. String -> a errorWithoutStackTrace String "Numeric.showInt: can't show negative numbers"|Bool otherwise =a -> ShowS forall a. Integral a => a -> ShowS go a n0 String cs0 wherego :: t -> ShowS go t n String cs |t n t -> t -> Bool forall a. Ord a => a -> a -> Bool < t 10=caseInt -> Char unsafeChr (Char -> Int ord Char '0'Int -> Int -> Int forall a. Num a => a -> a -> a + t -> Int forall a b. (Integral a, Num b) => a -> b fromIntegral t n )ofc :: Char c @(C# Char# _)->Char c Char -> ShowS forall a. a -> [a] -> [a] : String cs |Bool otherwise =caseInt -> Char unsafeChr (Char -> Int ord Char '0'Int -> Int -> Int forall a. Num a => a -> a -> a + t -> Int forall a b. (Integral a, Num b) => a -> b fromIntegral t r )ofc :: Char c @(C# Char# _)->t -> ShowS go t q (Char c Char -> ShowS forall a. a -> [a] -> [a] : String cs )where(t q ,t r )=t n t -> t -> (t, t) forall a. Integral a => a -> a -> (a, a) `quotRem` t 10-- Controlling the format and precision of floats. The code that-- implements the formatting itself is in @PrelNum@ to avoid-- mutual module deps.{-# SPECIALIZEshowEFloat ::Maybe Int ->Float ->ShowS ,Maybe Int ->Double ->ShowS #-}{-# SPECIALIZEshowFFloat ::Maybe Int ->Float ->ShowS ,Maybe Int ->Double ->ShowS #-}{-# SPECIALIZEshowGFloat ::Maybe Int ->Float ->ShowS ,Maybe Int ->Double ->ShowS #-}-- | Show a signed 'RealFloat' value-- using scientific (exponential) notation (e.g. @2.45e2@, @1.5e-3@).---- In the call @'showEFloat' digs val@, if @digs@ is 'Nothing',-- the value is shown to full precision; if @digs@ is @'Just' d@,-- then at most @d@ digits after the decimal point are shown.showEFloat ::(RealFloat a )=>Maybe Int ->a ->ShowS -- | Show a signed 'RealFloat' value-- using standard decimal notation (e.g. @245000@, @0.0015@).---- In the call @'showFFloat' digs val@, if @digs@ is 'Nothing',-- the value is shown to full precision; if @digs@ is @'Just' d@,-- then at most @d@ digits after the decimal point are shown.showFFloat ::(RealFloat a )=>Maybe Int ->a ->ShowS -- | Show a signed 'RealFloat' value-- using standard decimal notation for arguments whose absolute value lies-- between @0.1@ and @9,999,999@, and scientific notation otherwise.---- In the call @'showGFloat' digs val@, if @digs@ is 'Nothing',-- the value is shown to full precision; if @digs@ is @'Just' d@,-- then at most @d@ digits after the decimal point are shown.showGFloat ::(RealFloat a )=>Maybe Int ->a ->ShowS showEFloat :: forall a. RealFloat a => Maybe Int -> a -> ShowS showEFloat Maybe Int d a x =String -> ShowS showString (FFFormat -> Maybe Int -> a -> String forall a. RealFloat a => FFFormat -> Maybe Int -> a -> String formatRealFloat FFFormat FFExponent Maybe Int d a x )showFFloat :: forall a. RealFloat a => Maybe Int -> a -> ShowS showFFloat Maybe Int d a x =String -> ShowS showString (FFFormat -> Maybe Int -> a -> String forall a. RealFloat a => FFFormat -> Maybe Int -> a -> String formatRealFloat FFFormat FFFixed Maybe Int d a x )showGFloat :: forall a. RealFloat a => Maybe Int -> a -> ShowS showGFloat Maybe Int d a x =String -> ShowS showString (FFFormat -> Maybe Int -> a -> String forall a. RealFloat a => FFFormat -> Maybe Int -> a -> String formatRealFloat FFFormat FFGeneric Maybe Int d a x )-- | Show a signed 'RealFloat' value-- using standard decimal notation (e.g. @245000@, @0.0015@).---- This behaves as 'showFFloat', except that a decimal point-- is always guaranteed, even if not needed.---- @since 4.7.0.0showFFloatAlt ::(RealFloat a )=>Maybe Int ->a ->ShowS -- | Show a signed 'RealFloat' value-- using standard decimal notation for arguments whose absolute value lies-- between @0.1@ and @9,999,999@, and scientific notation otherwise.---- This behaves as 'showFFloat', except that a decimal point-- is always guaranteed, even if not needed.---- @since 4.7.0.0showGFloatAlt ::(RealFloat a )=>Maybe Int ->a ->ShowS showFFloatAlt :: forall a. RealFloat a => Maybe Int -> a -> ShowS showFFloatAlt Maybe Int d a x =String -> ShowS showString (FFFormat -> Maybe Int -> Bool -> a -> String forall a. RealFloat a => FFFormat -> Maybe Int -> Bool -> a -> String formatRealFloatAlt FFFormat FFFixed Maybe Int d Bool True a x )showGFloatAlt :: forall a. RealFloat a => Maybe Int -> a -> ShowS showGFloatAlt Maybe Int d a x =String -> ShowS showString (FFFormat -> Maybe Int -> Bool -> a -> String forall a. RealFloat a => FFFormat -> Maybe Int -> Bool -> a -> String formatRealFloatAlt FFFormat FFGeneric Maybe Int d Bool True a x ){- | Show a floating-point value in the hexadecimal format, similar to the @%a@ specifier in C's printf. >>> showHFloat (212.21 :: Double) "" "0x1.a86b851eb851fp7" >>> showHFloat (-12.76 :: Float) "" "-0x1.9851ecp3" >>> showHFloat (-0 :: Double) "" "-0x0p+0" -}showHFloat ::RealFloat a =>a ->ShowS showHFloat :: forall a. RealFloat a => a -> ShowS showHFloat =String -> ShowS showString (String -> ShowS) -> (a -> String) -> a -> ShowS forall b c a. (b -> c) -> (a -> b) -> a -> c . a -> String forall {a}. RealFloat a => a -> String fmt wherefmt :: a -> String fmt a x |a -> Bool forall a. RealFloat a => a -> Bool isNaN a x =String "NaN"|a -> Bool forall a. RealFloat a => a -> Bool isInfinite a x =(ifa x a -> a -> Bool forall a. Ord a => a -> a -> Bool < a 0thenString "-"elseString "")String -> ShowS forall a. [a] -> [a] -> [a] ++ String "Infinity"|a x a -> a -> Bool forall a. Ord a => a -> a -> Bool < a 0Bool -> Bool -> Bool || a -> Bool forall a. RealFloat a => a -> Bool isNegativeZero a x =Char '-'Char -> ShowS forall a. a -> [a] -> [a] : a -> String forall {a}. RealFloat a => a -> String cvt (-a x )|Bool otherwise =a -> String forall {a}. RealFloat a => a -> String cvt a x cvt :: a -> String cvt a x |a x a -> a -> Bool forall a. Eq a => a -> a -> Bool == a 0=String "0x0p+0"|Bool otherwise =caseInteger -> a -> ([Int], Int) forall a. RealFloat a => Integer -> a -> ([Int], Int) floatToDigits Integer 2a x ofr :: ([Int], Int) r @([],Int _)->ShowS forall a. HasCallStack => String -> a error ShowS -> ShowS forall a b. (a -> b) -> a -> b $ String "Impossible happened: showHFloat: "String -> ShowS forall a. [a] -> [a] -> [a] ++ ([Int], Int) -> String forall a. Show a => a -> String show ([Int], Int) r (Int d : [Int] ds ,Int e )->String "0x"String -> ShowS forall a. [a] -> [a] -> [a] ++ Int -> String forall a. Show a => a -> String show Int d String -> ShowS forall a. [a] -> [a] -> [a] ++ [Int] -> String forall {a}. Integral a => [a] -> String frac [Int] ds String -> ShowS forall a. [a] -> [a] -> [a] ++ String "p"String -> ShowS forall a. [a] -> [a] -> [a] ++ Int -> String forall a. Show a => a -> String show (Int e Int -> Int -> Int forall a. Num a => a -> a -> a - Int 1)-- Given binary digits, convert them to hex in blocks of 4-- Special case: If all 0's, just drop it.frac :: [a] -> String frac [a] digits |[a] -> Bool forall {a}. (Eq a, Num a) => [a] -> Bool allZ [a] digits =String ""|Bool otherwise =String "."String -> ShowS forall a. [a] -> [a] -> [a] ++ [a] -> String forall {a}. Integral a => [a] -> String hex [a] digits wherehex :: [a] -> String hex [a] ds =case[a] ds of[]->String ""[a a ]->a -> a -> a -> a -> ShowS forall {a}. Integral a => a -> a -> a -> a -> ShowS hexDigit a a a 0a 0a 0String ""[a a ,a b ]->a -> a -> a -> a -> ShowS forall {a}. Integral a => a -> a -> a -> a -> ShowS hexDigit a a a b a 0a 0String ""[a a ,a b ,a c ]->a -> a -> a -> a -> ShowS forall {a}. Integral a => a -> a -> a -> a -> ShowS hexDigit a a a b a c a 0String ""a a : a b : a c : a d : [a] r ->a -> a -> a -> a -> ShowS forall {a}. Integral a => a -> a -> a -> a -> ShowS hexDigit a a a b a c a d ([a] -> String hex [a] r )hexDigit :: a -> a -> a -> a -> ShowS hexDigit a a a b a c a d =a -> ShowS forall a. Integral a => a -> ShowS showHex (a 8a -> a -> a forall a. Num a => a -> a -> a * a a a -> a -> a forall a. Num a => a -> a -> a + a 4a -> a -> a forall a. Num a => a -> a -> a * a b a -> a -> a forall a. Num a => a -> a -> a + a 2a -> a -> a forall a. Num a => a -> a -> a * a c a -> a -> a forall a. Num a => a -> a -> a + a d )allZ :: [a] -> Bool allZ [a] xs =case[a] xs ofa x : [a] more ->a x a -> a -> Bool forall a. Eq a => a -> a -> Bool == a 0Bool -> Bool -> Bool && [a] -> Bool allZ [a] more []->Bool True -- ----------------------------------------------------------------------------- Integer printing functions-- | Shows a /non-negative/ 'Integral' number using the base specified by the-- first argument, and the character representation specified by the second.showIntAtBase ::Integral a =>a ->(Int ->Char )->a ->ShowS showIntAtBase :: forall a. Integral a => a -> (Int -> Char) -> a -> ShowS showIntAtBase a base Int -> Char toChr a n0 String r0 |a base a -> a -> Bool forall a. Ord a => a -> a -> Bool <= a 1=ShowS forall a. String -> a errorWithoutStackTrace (String "Numeric.showIntAtBase: applied to unsupported base "String -> ShowS forall a. [a] -> [a] -> [a] ++ Integer -> String forall a. Show a => a -> String show (a -> Integer forall a. Integral a => a -> Integer toInteger a base ))|a n0 a -> a -> Bool forall a. Ord a => a -> a -> Bool < a 0=ShowS forall a. String -> a errorWithoutStackTrace (String "Numeric.showIntAtBase: applied to negative number "String -> ShowS forall a. [a] -> [a] -> [a] ++ Integer -> String forall a. Show a => a -> String show (a -> Integer forall a. Integral a => a -> Integer toInteger a n0 ))|Bool otherwise =(a, a) -> ShowS showIt (a -> a -> (a, a) forall a. Integral a => a -> a -> (a, a) quotRem a n0 a base )String r0 whereshowIt :: (a, a) -> ShowS showIt (a n ,a d )String r =Char -> ShowS forall a b. a -> b -> b seq Char c ShowS -> ShowS forall a b. (a -> b) -> a -> b $ -- stricter than necessarycasea n ofa 0->String r' a _->(a, a) -> ShowS showIt (a -> a -> (a, a) forall a. Integral a => a -> a -> (a, a) quotRem a n a base )String r' wherec :: Char c =Int -> Char toChr (a -> Int forall a b. (Integral a, Num b) => a -> b fromIntegral a d )r' :: String r' =Char c Char -> ShowS forall a. a -> [a] -> [a] : String r -- | Show /non-negative/ 'Integral' numbers in base 16.showHex ::Integral a =>a ->ShowS showHex :: forall a. Integral a => a -> ShowS showHex =a -> (Int -> Char) -> a -> ShowS forall a. Integral a => a -> (Int -> Char) -> a -> ShowS showIntAtBase a 16Int -> Char intToDigit -- | Show /non-negative/ 'Integral' numbers in base 8.showOct ::Integral a =>a ->ShowS showOct :: forall a. Integral a => a -> ShowS showOct =a -> (Int -> Char) -> a -> ShowS forall a. Integral a => a -> (Int -> Char) -> a -> ShowS showIntAtBase a 8Int -> Char intToDigit -- | Show /non-negative/ 'Integral' numbers in base 2.showBin ::Integral a =>a ->ShowS showBin :: forall a. Integral a => a -> ShowS showBin =a -> (Int -> Char) -> a -> ShowS forall a. Integral a => a -> (Int -> Char) -> a -> ShowS showIntAtBase a 2Int -> Char intToDigit