X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=GHC%2FNum.lhs;h=76d6c8b1f1b82bbbf9db375e5c2a3d85fb398987;hb=de2b563a240bafc20b656729d1ecde0c890d22da;hp=611236c0e579c48e14918ecc11c5b6442369358a;hpb=63332a05565f860e5adc865f880e851ad5140caf;p=ghc-base.git diff --git a/GHC/Num.lhs b/GHC/Num.lhs index 611236c..76d6c8b 100644 --- a/GHC/Num.lhs +++ b/GHC/Num.lhs @@ -1,37 +1,32 @@ -% ------------------------------------------------------------------------------ -% $Id: Num.lhs,v 1.2 2001/07/31 13:09:11 simonmar Exp $ -% -% (c) The University of Glasgow, 1994-2000 -% - -\section[GHC.Num]{Module @GHC.Num@} - -The class - - Num - -and the type - - Integer - - \begin{code} -{-# OPTIONS -fno-implicit-prelude #-} +{-# OPTIONS_GHC -fno-implicit-prelude #-} +----------------------------------------------------------------------------- +-- | +-- Module : GHC.Num +-- Copyright : (c) The University of Glasgow 1994-2002 +-- License : see libraries/base/LICENSE +-- +-- Maintainer : cvs-ghc@haskell.org +-- Stability : internal +-- Portability : non-portable (GHC Extensions) +-- +-- The 'Num' class and the 'Integer' type. +-- +----------------------------------------------------------------------------- #include "MachDeps.h" -#if WORD_SIZE_IN_BYTES == 4 +#if SIZEOF_HSWORD == 4 #define LEFTMOST_BIT 2147483648 -#elif WORD_SIZE_IN_BYTES == 8 +#elif SIZEOF_HSWORD == 8 #define LEFTMOST_BIT 9223372036854775808 #else -#error Please define LEFTMOST_BIT to be 2^(WORD_SIZE_IN_BYTES*8-1) +#error Please define LEFTMOST_BIT to be 2^(SIZEOF_HSWORD*8-1) #endif module GHC.Num where import {-# SOURCE #-} GHC.Err import GHC.Base -import GHC.List import GHC.Enum import GHC.Show @@ -49,15 +44,37 @@ default () -- Double isn't available yet, %********************************************************* \begin{code} +-- | Basic numeric class. +-- +-- Minimal complete definition: all except 'negate' or @(-)@ class (Eq a, Show a) => Num a where (+), (-), (*) :: a -> a -> a + -- | Unary negation. negate :: a -> a - abs, signum :: a -> a + -- | Absolute value. + abs :: a -> a + -- | Sign of a number. + -- The functions 'abs' and 'signum' should satisfy the law: + -- + -- > abs x * signum x == x + -- + -- For real numbers, the 'signum' is either @-1@ (negative), @0@ (zero) + -- or @1@ (positive). + signum :: a -> a + -- | Conversion from an 'Integer'. + -- An integer literal represents the application of the function + -- 'fromInteger' to the appropriate value of type 'Integer', + -- so such literals have type @('Num' a) => a@. fromInteger :: Integer -> a x - y = x + negate y negate x = 0 - x +-- | the same as @'flip' ('-')@. +-- +-- Because @-@ is treated specially in the Haskell grammar, +-- @(-@ /e/@)@ is not a section, but an application of prefix negation. +-- However, @('subtract'@ /exp/@)@ is equivalent to the disallowed section. {-# INLINE subtract #-} subtract :: (Num a) => a -> a -> a subtract x y = y - x @@ -83,15 +100,9 @@ instance Num Int where | otherwise = 1 fromInteger = integer2Int -\end{code} - - -\begin{code} --- These can't go in GHC.Base with the defn of Int, because --- we don't have pairs defined at that time! quotRemInt :: Int -> Int -> (Int, Int) -a@(I# _) `quotRemInt` b@(I# _) = (a `quotInt` b, a `remInt` b) +quotRemInt a@(I# _) 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) @@ -99,7 +110,6 @@ 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{The @Integer@ type} @@ -107,9 +117,16 @@ divModInt x@(I# _) y@(I# _) = (x `divInt` y, x `modInt` y) %********************************************************* \begin{code} +-- | Arbitrary-precision integers. data Integer = S# Int# -- small integers +#ifndef ILX | J# Int# ByteArray# -- large integers +#else + | J# Void BigInteger -- .NET big ints + +foreign type dotnet "BigInteger" BigInteger +#endif \end{code} Convenient boxed Integer PrimOps. @@ -346,9 +363,9 @@ 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@(S# i) i2@(S# j) = if mulIntMayOflo# i j ==# 0# + then S# (i *# j) + 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 @@ -376,33 +393,29 @@ instance Enum Integer where {-# 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 + enumFrom x = enumDeltaInteger x 1 + enumFromThen x y = enumDeltaInteger x (y-x) + enumFromTo x lim = enumDeltaToInteger x 1 lim + enumFromThenTo x y lim = enumDeltaToInteger x (y-x) lim {-# 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 +"enumDeltaInteger" [~1] forall x y. enumDeltaInteger x y = build (\c _ -> enumDeltaIntegerFB c x y) +"efdtInteger" [~1] forall x y l.enumDeltaToInteger x y l = build (\c n -> enumDeltaToIntegerFB c n x y l) +"enumDeltaInteger" [1] enumDeltaIntegerFB (:) = enumDeltaInteger +"enumDeltaToInteger" [1] enumDeltaToIntegerFB (:) [] = enumDeltaToInteger #-} 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 +enumDeltaInteger :: Integer -> Integer -> [Integer] +enumDeltaInteger x d = x : enumDeltaInteger (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 +enumDeltaToInteger x delta lim | delta >= 0 = up_list x delta lim | otherwise = dn_list x delta lim @@ -436,7 +449,10 @@ dn_list x delta lim = go (x::Integer) \begin{code} instance Show Integer where showsPrec p n r - | n < 0 && p > 6 = '(' : jtos n (')' : r) + | p > 6 && n < 0 = '(' : jtos n (')' : r) + -- Minor point: testing p first gives better code + -- in the not-uncommon case where the p argument + -- is a constant | otherwise = jtos n r showList = showList__ (showsPrec 0)