X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Flib%2Fstd%2FPrelNum.lhs;h=a2bf83899259e0a49b6a807603384f51e8a7c598;hb=50027272414438955dbc41696541cbd25da55883;hp=08081353f35de6af763c98c4b3e2c8280058f10e;hpb=4d38d0728a1e6e899c23efd7a67060d45bf784cd;p=ghc-hetmet.git diff --git a/ghc/lib/std/PrelNum.lhs b/ghc/lib/std/PrelNum.lhs index 0808135..a2bf838 100644 --- a/ghc/lib/std/PrelNum.lhs +++ b/ghc/lib/std/PrelNum.lhs @@ -1,126 +1,60 @@ +% ------------------------------------------------------------------------------ +% $Id: PrelNum.lhs,v 1.37 2001/02/28 00:01:03 qrczak Exp $ % -% (c) The AQUA Project, Glasgow University, 1994-1996 +% (c) The University of Glasgow, 1994-2000 % \section[PrelNum]{Module @PrelNum@} +The class + + Num + +and the type + + Integer + + \begin{code} {-# OPTIONS -fno-implicit-prelude #-} module PrelNum where -import PrelBase -import Ix import {-# SOURCE #-} PrelErr +import PrelBase +import PrelList +import PrelEnum +import PrelShow + +infixl 7 * +infixl 6 +, - -infixr 8 ^, ^^, ** -infixl 7 %, /, `quot`, `rem`, `div`, `mod` +default () -- Double isn't available yet, + -- and we shouldn't be using defaults anyway \end{code} %********************************************************* %* * -\subsection{Standard numeric classes} +\subsection{Standard numeric class} %* * %********************************************************* \begin{code} -class (Num a, Ord a) => Real a where - toRational :: a -> Rational - -class (Real a, Enum a) => Integral a where - quot, rem, div, mod :: a -> a -> a - quotRem, divMod :: a -> a -> (a,a) - toInteger :: a -> Integer - toInt :: a -> Int -- partain: Glasgow extension - - n `quot` d = q where (q,_) = quotRem n d - n `rem` d = r where (_,r) = quotRem n d - n `div` d = q where (q,_) = divMod n d - n `mod` d = r where (_,r) = divMod n d - divMod n d = if signum r == negate (signum d) then (q-1, r+d) else qr - where qr@(q,r) = quotRem n d - -class (Num a) => Fractional a where - (/) :: a -> a -> a - recip :: a -> a - fromRational :: Rational -> a - - recip x = 1 / x - x / y = x * recip y - -class (Fractional a) => Floating a where - pi :: a - exp, log, sqrt :: a -> a - (**), logBase :: a -> a -> a - sin, cos, tan :: a -> a - asin, acos, atan :: a -> a - sinh, cosh, tanh :: a -> a - asinh, acosh, atanh :: a -> a - - x ** y = exp (log x * y) - logBase x y = log y / log x - sqrt x = x ** 0.5 - tan x = sin x / cos x - tanh x = sinh x / cosh x - -class (Real a, Fractional a) => RealFrac a where - properFraction :: (Integral b) => a -> (b,a) - truncate, round :: (Integral b) => a -> b - ceiling, floor :: (Integral b) => a -> b - - truncate x = m where (m,_) = properFraction x - - round x = let (n,r) = properFraction x - m = if r < 0 then n - 1 else n + 1 - in case signum (abs r - 0.5) of - -1 -> n - 0 -> if even n then n else m - 1 -> m - - ceiling x = if r > 0 then n + 1 else n - where (n,r) = properFraction x - - floor x = if r < 0 then n - 1 else n - where (n,r) = properFraction x - -class (RealFrac a, Floating a) => RealFloat a where - floatRadix :: a -> Integer - floatDigits :: a -> Int - floatRange :: a -> (Int,Int) - decodeFloat :: a -> (Integer,Int) - encodeFloat :: Integer -> Int -> a - exponent :: a -> Int - significand :: a -> a - scaleFloat :: Int -> a -> a - isNaN, isInfinite, isDenormalized, isNegativeZero, isIEEE - :: a -> Bool - atan2 :: a -> a -> a - - - exponent x = if m == 0 then 0 else n + floatDigits x - where (m,n) = decodeFloat x - - significand x = encodeFloat m (negate (floatDigits x)) - where (m,_) = decodeFloat x - - scaleFloat k x = encodeFloat m (n+k) - where (m,n) = decodeFloat x - - atan2 y x - | x > 0 = atan (y/x) - | x == 0 && y > 0 = pi/2 - | x < 0 && y > 0 = pi + atan (y/x) - |(x <= 0 && y < 0) || - (x < 0 && isNegativeZero y) || - (isNegativeZero x && isNegativeZero y) - = -atan2 (-y) x - | y == 0 && (x < 0 || isNegativeZero x) - = pi -- must be after the previous test on zero y - | x==0 && y==0 = y -- must be after the other double zero tests - | otherwise = x + y -- x or y is a NaN, return a NaN (via +) - +class (Eq a, Show a) => Num a where + (+), (-), (*) :: a -> a -> a + negate :: a -> a + abs, signum :: a -> a + fromInteger :: Integer -> a + + x - y = x + negate y + negate x = 0 - x + +{-# INLINE subtract #-} +subtract :: (Num a) => a -> a -> a +subtract x y = y - x \end{code} + %********************************************************* %* * \subsection{Instances for @Int@} @@ -128,283 +62,386 @@ class (RealFrac a, Floating a) => RealFloat a where %********************************************************* \begin{code} -instance Real Int where - toRational x = toInteger x % 1 - -instance Integral Int where - a@(I# _) `quotRem` b@(I# _) = (a `quotInt` b, a `remInt` b) - -- OK, so I made it a little stricter. Shoot me. (WDP 94/10) +instance Num Int where + (+) = plusInt + (-) = minusInt + negate = negateInt + (*) = timesInt + abs n = if n `geInt` 0 then n else negateInt n + + signum n | n `ltInt` 0 = negateInt 1 + | n `eqInt` 0 = 0 + | otherwise = 1 + + fromInteger = integer2Int +\end{code} - -- Following chks for zero divisor are non-standard (WDP) - a `quot` b = if b /= 0 - then a `quotInt` b - else error "Prelude.Integral.quot{Int}: divide by 0" - a `rem` b = if b /= 0 - then a `remInt` b - else error "Prelude.Integral.rem{Int}: divide by 0" - - x `div` y = if x > 0 && y < 0 then quotInt (x-y-1) y - else if x < 0 && y > 0 then quotInt (x-y+1) y - else quotInt x y - x `mod` y = if x > 0 && y < 0 || x < 0 && y > 0 then - if r/=0 then r+y else 0 - else - r - where r = remInt x y - - divMod x@(I# _) y@(I# _) = (x `div` y, x `mod` y) - -- Stricter. Sorry if you don't like it. (WDP 94/10) ---OLD: even x = eqInt (x `mod` 2) 0 ---OLD: odd x = neInt (x `mod` 2) 0 +\begin{code} +-- These can't go in PrelBase with the defn of Int, because +-- we don't have pairs defined at that time! - toInteger (I# i) = int2Integer i -- give back a full-blown Integer - toInt x = x +quotRemInt :: Int -> Int -> (Int, Int) +a@(I# _) `quotRemInt` b@(I# _) = (a `quotInt` b, a `remInt` b) + -- OK, so I made it a little stricter. Shoot me. (WDP 94/10) +divModInt :: Int -> Int -> (Int, Int) +divModInt x@(I# _) y@(I# _) = (x `divInt` y, x `modInt` y) + -- Stricter. Sorry if you don't like it. (WDP 94/10) \end{code} + %********************************************************* %* * -\subsection{Instances for @Integer@} +\subsection{The @Integer@ type} %* * %********************************************************* \begin{code} -instance Ord Integer where - (J# a1 s1 d1) <= (J# a2 s2 d2) - = (cmpInteger# a1 s1 d1 a2 s2 d2) <=# 0# - - (J# a1 s1 d1) < (J# a2 s2 d2) - = (cmpInteger# a1 s1 d1 a2 s2 d2) <# 0# - - (J# a1 s1 d1) >= (J# a2 s2 d2) - = (cmpInteger# a1 s1 d1 a2 s2 d2) >=# 0# - - (J# a1 s1 d1) > (J# a2 s2 d2) - = (cmpInteger# a1 s1 d1 a2 s2 d2) ># 0# - - x@(J# a1 s1 d1) `max` y@(J# a2 s2 d2) - = if ((cmpInteger# a1 s1 d1 a2 s2 d2) ># 0#) then x else y - - x@(J# a1 s1 d1) `min` y@(J# a2 s2 d2) - = if ((cmpInteger# a1 s1 d1 a2 s2 d2) <# 0#) then x else y - - compare (J# a1 s1 d1) (J# a2 s2 d2) - = case cmpInteger# a1 s1 d1 a2 s2 d2 of { res# -> - if res# <# 0# then LT else - if res# ># 0# then GT else EQ - } +data Integer + = S# Int# -- small integers + | J# Int# ByteArray# -- large integers +\end{code} -instance Num Integer where - (+) (J# a1 s1 d1) (J# a2 s2 d2) - = case plusInteger# a1 s1 d1 a2 s2 d2 of (# a, s, d #) -> J# a s d +Convenient boxed Integer PrimOps. - (-) (J# a1 s1 d1) (J# a2 s2 d2) - = case minusInteger# a1 s1 d1 a2 s2 d2 of (# a, s, d #) -> J# a s d +\begin{code} +zeroInteger :: Integer +zeroInteger = S# 0# - negate (J# a s d) - = case negateInteger# a s d of (# a1, s1, d1 #) -> J# a1 s1 d1 +int2Integer :: Int -> Integer +{-# INLINE int2Integer #-} +int2Integer (I# i) = S# i - (*) (J# a1 s1 d1) (J# a2 s2 d2) - = case timesInteger# a1 s1 d1 a2 s2 d2 of (# a, s, d #) -> J# a s d +integer2Int :: Integer -> Int +integer2Int (S# i) = I# i +integer2Int (J# s d) = case (integer2Int# s d) of { n# -> I# n# } - -- ORIG: abs n = if n >= 0 then n else -n +toBig (S# i) = case int2Integer# i of { (# s, d #) -> J# s d } +toBig i@(J# _ _) = i +\end{code} - abs n@(J# a1 s1 d1) - = case 0 of { J# a2 s2 d2 -> - if (cmpInteger# a1 s1 d1 a2 s2 d2) >=# 0# - then n - else case negateInteger# a1 s1 d1 of (# a, s, d #) -> J# a s d - } - - signum (J# a1 s1 d1) - = case 0 of { J# a2 s2 d2 -> - let - cmp = cmpInteger# a1 s1 d1 a2 s2 d2 - in - if cmp ># 0# then 1 - else if cmp ==# 0# then 0 - else (negate 1) - } - fromInteger x = x +%********************************************************* +%* * +\subsection{Dividing @Integers@} +%* * +%********************************************************* - fromInt (I# i) = int2Integer i +\begin{code} +quotRemInteger :: Integer -> Integer -> (Integer, Integer) +quotRemInteger a@(S# (-2147483648#)) b = quotRemInteger (toBig a) b +quotRemInteger (S# i) (S# j) + = case quotRemInt (I# i) (I# j) of ( I# i, I# j ) -> ( S# i, S# j ) +quotRemInteger i1@(J# _ _) i2@(S# _) = quotRemInteger i1 (toBig i2) +quotRemInteger i1@(S# _) i2@(J# _ _) = quotRemInteger (toBig i1) i2 +quotRemInteger (J# s1 d1) (J# s2 d2) + = case (quotRemInteger# s1 d1 s2 d2) of + (# s3, d3, s4, d4 #) + -> (J# s3 d3, J# s4 d4) + +divModInteger a@(S# (-2147483648#)) b = divModInteger (toBig a) b +divModInteger (S# i) (S# j) + = case divModInt (I# i) (I# j) of ( I# i, I# j ) -> ( S# i, S# j) +divModInteger i1@(J# _ _) i2@(S# _) = divModInteger i1 (toBig i2) +divModInteger i1@(S# _) i2@(J# _ _) = divModInteger (toBig i1) i2 +divModInteger (J# s1 d1) (J# s2 d2) + = case (divModInteger# s1 d1 s2 d2) of + (# s3, d3, s4, d4 #) + -> (J# s3 d3, J# s4 d4) + +remInteger :: Integer -> Integer -> Integer +remInteger ia 0 + = error "Prelude.Integral.rem{Integer}: divide by 0" +remInteger a@(S# (-2147483648#)) b = remInteger (toBig a) b +remInteger (S# a) (S# b) = S# (remInt# a b) +{- Special case doesn't work, because a 1-element J# has the range + -(2^32-1) -- 2^32-1, whereas S# has the range -2^31 -- (2^31-1) +remInteger ia@(S# a) (J# sb b) + | sb ==# 1# = S# (remInt# a (word2Int# (integer2Word# sb b))) + | sb ==# -1# = S# (remInt# a (0# -# (word2Int# (integer2Word# sb b)))) + | 0# <# sb = ia + | otherwise = S# (0# -# a) +-} +remInteger ia@(S# _) ib@(J# _ _) = remInteger (toBig ia) ib +remInteger (J# sa a) (S# b) + = case int2Integer# b of { (# sb, b #) -> + case remInteger# sa a sb b of { (# sr, r #) -> + S# (sr *# (word2Int# (integer2Word# sr r))) }} +remInteger (J# sa a) (J# sb b) + = case remInteger# sa a sb b of (# sr, r #) -> J# sr r + +quotInteger :: Integer -> Integer -> Integer +quotInteger ia 0 + = error "Prelude.Integral.quot{Integer}: divide by 0" +quotInteger a@(S# (-2147483648#)) b = quotInteger (toBig a) b +quotInteger (S# a) (S# b) = S# (quotInt# a b) +{- Special case disabled, see remInteger above +quotInteger (S# a) (J# sb b) + | sb ==# 1# = S# (quotInt# a (word2Int# (integer2Word# sb b))) + | sb ==# -1# = S# (quotInt# a (0# -# (word2Int# (integer2Word# sb b)))) + | otherwise = zeroInteger +-} +quotInteger ia@(S# _) ib@(J# _ _) = quotInteger (toBig ia) ib +quotInteger (J# sa a) (S# b) + = case int2Integer# b of { (# sb, b #) -> + case quotInteger# sa a sb b of (# sq, q #) -> J# sq q } +quotInteger (J# sa a) (J# sb b) + = case quotInteger# sa a sb b of (# sg, g #) -> J# sg g +\end{code} -instance Real Integer where - toRational x = x % 1 -instance Integral Integer where - quotRem (J# a1 s1 d1) (J# a2 s2 d2) - = case (quotRemInteger# a1 s1 d1 a2 s2 d2) of - (# a3, s3, d3, a4, s4, d4 #) - -> (J# a3 s3 d3, J# a4 s4 d4) -{- USING THE UNDERLYING "GMP" CODE IS DUBIOUS FOR NOW: +\begin{code} +gcdInteger :: Integer -> Integer -> Integer +-- SUP: Do we really need the first two cases? +gcdInteger a@(S# (-2147483648#)) b = gcdInteger (toBig a) b +gcdInteger a b@(S# (-2147483648#)) = gcdInteger a (toBig b) +gcdInteger (S# a) (S# b) = case gcdInt (I# a) (I# b) of { I# c -> S# c } +gcdInteger ia@(S# 0#) ib@(J# 0# _) = error "PrelNum.gcdInteger: gcd 0 0 is undefined" +gcdInteger ia@(S# a) ib@(J# sb b) + | a ==# 0# = abs ib + | sb ==# 0# = abs ia + | otherwise = S# (gcdIntegerInt# absSb b absA) + where absA = if a <# 0# then negateInt# a else a + absSb = if sb <# 0# then negateInt# sb else sb +gcdInteger ia@(J# _ _) ib@(S# _) = gcdInteger ib ia +gcdInteger (J# 0# _) (J# 0# _) = error "PrelNum.gcdInteger: gcd 0 0 is undefined" +gcdInteger (J# sa a) (J# sb b) + = case gcdInteger# sa a sb b of (# sg, g #) -> J# sg g + +lcmInteger :: Integer -> Integer -> Integer +lcmInteger a 0 + = zeroInteger +lcmInteger 0 b + = zeroInteger +lcmInteger a b + = (divExact aa (gcdInteger aa ab)) * ab + where aa = abs a + ab = abs b + +divExact :: Integer -> Integer -> Integer +divExact a@(S# (-2147483648#)) b = divExact (toBig a) b +divExact (S# a) (S# b) = S# (quotInt# a b) +divExact (S# a) (J# sb b) + = S# (quotInt# a (sb *# (word2Int# (integer2Word# sb b)))) +divExact (J# sa a) (S# b) + = case int2Integer# b of + (# sb, b #) -> case divExactInteger# sa a sb b of (# sd, d #) -> J# sd d +divExact (J# sa a) (J# sb b) + = case divExactInteger# sa a sb b of (# sd, d #) -> J# sd d +\end{code} - divMod (J# a1 s1 d1) (J# a2 s2 d2) - = case (divModInteger# a1 s1 d1 a2 s2 d2) of - Return2GMPs a3 s3 d3 a4 s4 d4 - -> (J# a3 s3 d3, J# a4 s4 d4) --} - toInteger n = n - toInt (J# a s d) = case (integer2Int# a s d) of { n# -> I# n# } - - -- the rest are identical to the report default methods; - -- you get slightly better code if you let the compiler - -- see them right here: - n `quot` d = if d /= 0 then q else - error "Prelude.Integral.quot{Integer}: divide by 0" - where (q,_) = quotRem n d - n `rem` d = if d /= 0 then r else - error "Prelude.Integral.rem{Integer}: divide by 0" - where (_,r) = quotRem n d - n `div` d = q where (q,_) = divMod n d - n `mod` d = r where (_,r) = divMod n d - - divMod n d = case (quotRem n d) of { qr@(q,r) -> - if signum r == negate (signum d) then (q - 1, r+d) else qr } - -- Case-ified by WDP 94/10 -instance Enum Integer where - succ x = x + 1 - pred x = x - 1 - toEnum n = toInteger n - fromEnum n = toInt n - enumFrom n = n : enumFrom (n + 1) - enumFromThen e1 e2 = en' e1 (e2 - e1) - where en' a b = a : en' (a + b) b - enumFromTo n m - | n <= m = takeWhile (<= m) (enumFrom n) - | otherwise = takeWhile (>= m) (enumFromThen n (n-1)) - enumFromThenTo n m p = takeWhile pred (enumFromThen n m) - where - pred | m >= n = (<= p) - | otherwise = (>= p) - -instance Show Integer where - showsPrec x = showSignedInteger x - showList = showList__ (showsPrec 0) - - -instance Ix Integer where - range (m,n) - | m <= n = [m..n] - | otherwise = [] - - index b@(m,_) i - | inRange b i = fromInteger (i - m) - | otherwise = indexIntegerError i b - inRange (m,n) i = m <= i && i <= n - --- Sigh, really want to use helper function in Ix, but --- module deps. are too painful. -{-# NOINLINE indexIntegerError #-} -indexIntegerError :: Integer -> (Integer,Integer) -> a -indexIntegerError i rng - = error (showString "Ix{Integer}.index: Index " . - showParen True (showsPrec 0 i) . - showString " out of range " $ - showParen True (showsPrec 0 rng) "") - -showSignedInteger :: Int -> Integer -> ShowS -showSignedInteger p n r - | n < 0 && p > 6 = '(':jtos n (')':r) - | otherwise = jtos n r +%********************************************************* +%* * +\subsection{The @Integer@ instances for @Eq@, @Ord@} +%* * +%********************************************************* -jtos :: Integer -> String -> String -jtos i rs - | i < 0 = '-' : jtos' (-i) rs - | otherwise = jtos' i rs - where - jtos' :: Integer -> String -> String - jtos' n cs - | n < 10 = chr (fromInteger n + (ord_0::Int)) : cs - | otherwise = jtos' q (chr (toInt r + (ord_0::Int)) : cs) - where - (q,r) = n `quotRem` 10 +\begin{code} +instance Eq Integer where + (S# i) == (S# j) = i ==# j + (S# i) == (J# s d) = cmpIntegerInt# s d i ==# 0# + (J# s d) == (S# i) = cmpIntegerInt# s d i ==# 0# + (J# s1 d1) == (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) ==# 0# + + (S# i) /= (S# j) = i /=# j + (S# i) /= (J# s d) = cmpIntegerInt# s d i /=# 0# + (J# s d) /= (S# i) = cmpIntegerInt# s d i /=# 0# + (J# s1 d1) /= (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) /=# 0# + +------------------------------------------------------------------------ +instance Ord Integer where + (S# i) <= (S# j) = i <=# j + (J# s d) <= (S# i) = cmpIntegerInt# s d i <=# 0# + (S# i) <= (J# s d) = cmpIntegerInt# s d i >=# 0# + (J# s1 d1) <= (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) <=# 0# + + (S# i) > (S# j) = i ># j + (J# s d) > (S# i) = cmpIntegerInt# s d i ># 0# + (S# i) > (J# s d) = cmpIntegerInt# s d i <# 0# + (J# s1 d1) > (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) ># 0# + + (S# i) < (S# j) = i <# j + (J# s d) < (S# i) = cmpIntegerInt# s d i <# 0# + (S# i) < (J# s d) = cmpIntegerInt# s d i ># 0# + (J# s1 d1) < (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) <# 0# + + (S# i) >= (S# j) = i >=# j + (J# s d) >= (S# i) = cmpIntegerInt# s d i >=# 0# + (S# i) >= (J# s d) = cmpIntegerInt# s d i <=# 0# + (J# s1 d1) >= (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) >=# 0# + + compare (S# i) (S# j) + | i ==# j = EQ + | i <=# j = LT + | otherwise = GT + compare (J# s d) (S# i) + = case cmpIntegerInt# s d i of { res# -> + if res# <# 0# then LT else + if res# ># 0# then GT else EQ + } + compare (S# i) (J# s d) + = case cmpIntegerInt# s d i of { res# -> + if res# ># 0# then LT else + if res# <# 0# then GT else EQ + } + compare (J# s1 d1) (J# s2 d2) + = case cmpInteger# s1 d1 s2 d2 of { res# -> + if res# <# 0# then LT else + if res# ># 0# then GT else EQ + } \end{code} + %********************************************************* %* * -\subsection{The @Ratio@ and @Rational@ types} +\subsection{The @Integer@ instances for @Num@} %* * %********************************************************* \begin{code} -data (Integral a) => Ratio a = !a :% !a deriving (Eq) -type Rational = Ratio Integer +instance Num Integer where + (+) = plusInteger + (-) = minusInteger + (*) = timesInteger + negate = negateInteger + fromInteger x = x -{-# SPECIALISE (%) :: Integer -> Integer -> Rational #-} -(%) :: (Integral a) => a -> a -> Ratio a -numerator, denominator :: (Integral a) => Ratio a -> a + -- ORIG: abs n = if n >= 0 then n else -n + abs (S# (-2147483648#)) = 2147483648 + abs (S# i) = case abs (I# i) of I# j -> S# j + abs n@(J# s d) = if (s >=# 0#) then n else J# (negateInt# s) d + + signum (S# i) = case signum (I# i) of I# j -> S# j + signum (J# s d) + = let + cmp = cmpIntegerInt# s d 0# + in + if cmp ># 0# then S# 1# + else if cmp ==# 0# then S# 0# + else S# (negateInt# 1#) + +plusInteger i1@(S# i) i2@(S# j) = case addIntC# i j of { (# r, c #) -> + if c ==# 0# then S# r + else toBig i1 + toBig i2 } +plusInteger i1@(J# _ _) i2@(S# _) = i1 + toBig i2 +plusInteger i1@(S# _) i2@(J# _ _) = toBig i1 + i2 +plusInteger (J# s1 d1) (J# s2 d2) = case plusInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d + +minusInteger i1@(S# i) i2@(S# j) = case subIntC# i j of { (# r, c #) -> + if c ==# 0# then S# r + else toBig i1 - toBig i2 } +minusInteger i1@(J# _ _) i2@(S# _) = i1 - toBig i2 +minusInteger i1@(S# _) i2@(J# _ _) = toBig i1 - i2 +minusInteger (J# s1 d1) (J# s2 d2) = case minusInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d + +timesInteger i1@(S# i) i2@(S# j) = case mulIntC# i j of { (# r, c #) -> + if c ==# 0# then S# r + else toBig i1 * toBig i2 } +timesInteger i1@(J# _ _) i2@(S# _) = i1 * toBig i2 +timesInteger i1@(S# _) i2@(J# _ _) = toBig i1 * i2 +timesInteger (J# s1 d1) (J# s2 d2) = case timesInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d + +negateInteger (S# (-2147483648#)) = 2147483648 +negateInteger (S# i) = S# (negateInt# i) +negateInteger (J# s d) = J# (negateInt# s) d \end{code} -\tr{reduce} is a subsidiary function used only in this module . -It normalises a ratio by dividing both numerator and denominator by -their greatest common divisor. -\begin{code} -reduce :: (Integral a) => a -> a -> Ratio a -reduce _ 0 = error "Ratio.%: zero denominator" -reduce x y = (x `quot` d) :% (y `quot` d) - where d = gcd x y -\end{code} +%********************************************************* +%* * +\subsection{The @Integer@ instance for @Enum@} +%* * +%********************************************************* \begin{code} -x % y = reduce (x * signum y) (abs y) - -numerator (x :% _) = x -denominator (_ :% y) = y +instance Enum Integer where + succ x = x + 1 + pred x = x - 1 + toEnum n = int2Integer n + fromEnum n = integer2Int n + + {-# INLINE enumFrom #-} + {-# INLINE enumFromThen #-} + {-# INLINE enumFromTo #-} + {-# INLINE enumFromThenTo #-} + enumFrom x = efdInteger x 1 + enumFromThen x y = efdInteger x (y-x) + enumFromTo x lim = efdtInteger x 1 lim + enumFromThenTo x y lim = efdtInteger x (y-x) lim + + +efdInteger = enumDeltaIntegerList +efdtInteger = enumDeltaToIntegerList + +{-# RULES +"efdInteger" forall x y. efdInteger x y = build (\c _ -> enumDeltaIntegerFB c x y) +"efdtInteger" forall x y l.efdtInteger x y l = build (\c n -> enumDeltaToIntegerFB c n x y l) +"enumDeltaInteger" enumDeltaIntegerFB (:) = enumDeltaIntegerList +"enumDeltaToInteger" enumDeltaToIntegerFB (:) [] = enumDeltaToIntegerList + #-} + +enumDeltaIntegerFB :: (Integer -> b -> b) -> Integer -> Integer -> b +enumDeltaIntegerFB c x d = x `c` enumDeltaIntegerFB c (x+d) d + +enumDeltaIntegerList :: Integer -> Integer -> [Integer] +enumDeltaIntegerList x d = x : enumDeltaIntegerList (x+d) d + +enumDeltaToIntegerFB c n x delta lim + | delta >= 0 = up_fb c n x delta lim + | otherwise = dn_fb c n x delta lim + +enumDeltaToIntegerList x delta lim + | delta >= 0 = up_list x delta lim + | otherwise = dn_list x delta lim + +up_fb c n x delta lim = go (x::Integer) + where + go x | x > lim = n + | otherwise = x `c` go (x+delta) +dn_fb c n x delta lim = go (x::Integer) + where + go x | x < lim = n + | otherwise = x `c` go (x+delta) + +up_list x delta lim = go (x::Integer) + where + go x | x > lim = [] + | otherwise = x : go (x+delta) +dn_list x delta lim = go (x::Integer) + where + go x | x < lim = [] + | otherwise = x : go (x+delta) \end{code} + %********************************************************* %* * -\subsection{Overloaded numeric functions} +\subsection{The @Integer@ instances for @Show@} %* * %********************************************************* \begin{code} -even, odd :: (Integral a) => a -> Bool -even n = n `rem` 2 == 0 -odd = not . even - -{-# SPECIALISE gcd :: - Int -> Int -> Int, - Integer -> Integer -> Integer #-} -gcd :: (Integral a) => a -> a -> a -gcd 0 0 = error "Prelude.gcd: gcd 0 0 is undefined" -gcd x y = gcd' (abs x) (abs y) - where gcd' a 0 = a - gcd' a b = gcd' b (a `rem` b) - -{-# SPECIALISE lcm :: - Int -> Int -> Int, - Integer -> Integer -> Integer #-} -lcm :: (Integral a) => a -> a -> a -lcm _ 0 = 0 -lcm 0 _ = 0 -lcm x y = abs ((x `quot` (gcd x y)) * y) - -{-# SPECIALISE (^) :: - Integer -> Integer -> Integer, - Integer -> Int -> Integer, - Int -> Int -> Int #-} -(^) :: (Num a, Integral b) => a -> b -> a -_ ^ 0 = 1 -x ^ n | n > 0 = f x (n-1) x - where f _ 0 y = y - f a d y = g a d where - g b i | even i = g (b*b) (i `quot` 2) - | otherwise = f b (i-1) (b*y) -_ ^ _ = error "Prelude.^: negative exponent" - -{- SPECIALISE (^^) :: - Double -> Int -> Double, - Rational -> Int -> Rational #-} -(^^) :: (Fractional a, Integral b) => a -> b -> a -x ^^ n = if n >= 0 then x^n else recip (x^(negate n)) +instance Show Integer where + showsPrec p n r + | n < 0 && p > 6 = '(' : jtos n (')' : r) + | otherwise = jtos n r + showList = showList__ (showsPrec 0) +jtos :: Integer -> String -> String +jtos n cs + | n < 0 = '-' : jtos' (-n) cs + | otherwise = jtos' n cs + where + jtos' :: Integer -> String -> String + jtos' n cs + | n < 10 = case unsafeChr (ord '0' + fromInteger n) of + c@(C# _) -> c:cs + | otherwise = case unsafeChr (ord '0' + fromInteger r) of + c@(C# _) -> jtos' q (c:cs) + where + (q,r) = n `quotRemInteger` 10 \end{code} -