diff --git a/GHC/Integer.hs b/GHC/Integer.hs index c9a400f3456b88a1552e03fb48e17f1ff43708c3..d00e183ab9e250e14146b904749d800a480361a2 100644 --- a/GHC/Integer.hs +++ b/GHC/Integer.hs @@ -1,10 +1,12 @@ -{-# LANGUAGE NoImplicitPrelude, BangPatterns #-} +{-# LANGUAGE CPP, MagicHash, ForeignFunctionInterface, + NoImplicitPrelude, BangPatterns, UnboxedTuples, + UnliftedFFITypes #-} ----------------------------------------------------------------------------- -- | -- Module : GHC.Integer --- Copyright : (c) Ian Lnyagh 2007-2008 +-- Copyright : (c) Ian Lynagh 2007-2008 -- License : BSD3 -- -- Maintainer : igloo@earth.li @@ -32,9 +34,12 @@ module GHC.Integer ( encodeDoubleInteger, decodeDoubleInteger, doubleFromInteger, -- gcdInteger, lcmInteger, -- XXX andInteger, orInteger, xorInteger, complementInteger, + shiftLInteger, shiftRInteger, hashInteger, ) where +import GHC.Integer.Type + import GHC.Bool import GHC.Ordering import GHC.Prim @@ -50,8 +55,6 @@ errorInteger = Positive errorPositive errorPositive :: Positive errorPositive = Some 47## None -- Random number -data Integer = Positive !Positive | Negative !Positive | Naught - smallInteger :: Int# -> Integer smallInteger i = if i >=# 0# then wordToInteger (int2Word# i) else -- XXX is this right for -minBound? @@ -268,6 +271,17 @@ Negative x `xorInteger` Negative y = let x' = x `minusPositive` onePositive complementInteger :: Integer -> Integer complementInteger x = negativeOneInteger `minusInteger` x +shiftLInteger :: Integer -> Int# -> Integer +shiftLInteger (Positive p) i = Positive (shiftLPositive p i) +shiftLInteger (Negative n) i = Negative (shiftLPositive n i) +shiftLInteger Naught _ = Naught + +shiftRInteger :: Integer -> Int# -> Integer +shiftRInteger (Positive p) i = shiftRPositive p i +shiftRInteger j@(Negative _) i + = complementInteger (shiftRInteger (complementInteger j) i) +shiftRInteger Naught _ = Naught + twosComplementPositive :: Positive -> DigitsOnes twosComplementPositive p = flipBits (p `minusPositive` onePositive) @@ -392,23 +406,9 @@ hashInteger (!_) = 42# ------------------------------------------------------------------- -- The hard work is done on positive numbers --- Least significant bit is first - --- Positive's have the property that they contain at least one Bit, --- and their last Bit is One. -type Positive = Digits -type Positives = List Positive - -data Digits = Some !Digit !Digits - | None -type Digit = Word# - -- XXX Could move () above us data Unit = Unit --- XXX Could move [] above us -data List a = Nil | Cons a (List a) - onePositive :: Positive onePositive = Some 1## None @@ -614,10 +614,17 @@ splitHalves :: Digit -> (# {- High -} Digit, {- Low -} Digit #) splitHalves (!x) = (# x `uncheckedShiftRL#` highHalfShift Unit, x `and#` lowHalfMask Unit #) --- Assumes 0 <= i <= 31 +-- Assumes 0 <= i shiftLPositive :: Positive -> Int# -> Positive -shiftLPositive None (!_) = None -- XXX Can't happen -shiftLPositive (!p) (!i) = +shiftLPositive p i + = if i >=# WORD_SIZE_IN_BITS# + then shiftLPositive (Some 0## p) (i -# WORD_SIZE_IN_BITS#) + else smallShiftLPositive p i + +-- Assumes 0 <= i < WORD_SIZE_IN_BITS# +smallShiftLPositive :: Positive -> Int# -> Positive +smallShiftLPositive (!p) 0# = p +smallShiftLPositive (!p) (!i) = case WORD_SIZE_IN_BITS# -# i of j -> let f carry None = if carry `eqWord#` 0## then None @@ -629,6 +636,23 @@ shiftLPositive (!p) (!i) = Some (me `or#` carry) (f carry' ws) in f 0## p +-- Assumes 0 <= i +shiftRPositive :: Positive -> Int# -> Integer +shiftRPositive None _ = Naught +shiftRPositive p@(Some _ q) i + = if i >=# WORD_SIZE_IN_BITS# + then shiftRPositive q (i -# WORD_SIZE_IN_BITS#) + else smallShiftRPositive p i + +-- Assumes 0 <= i < WORD_SIZE_IN_BITS# +smallShiftRPositive :: Positive -> Int# -> Integer +smallShiftRPositive (!p) (!i) = + if i ==# 0# + then Positive p + else case smallShiftLPositive p (WORD_SIZE_IN_BITS# -# i) of + Some _ p'@(Some _ _) -> Positive p' + _ -> Naught + -- Long division quotRemPositive :: Positive -> Positive -> (# Integer, Integer #) (!xs) `quotRemPositive` (!ys) @@ -641,7 +665,7 @@ quotRemPositive :: Positive -> Positive -> (# Integer, Integer #) mkSubtractors (!n) = if n ==# 0# then Cons ys Nil - else Cons (ys `shiftLPositive` n) + else Cons (ys `smallShiftLPositive` n) (mkSubtractors (n -# 1#)) -- The main function. Go the the end of xs, then walk diff --git a/GHC/Integer/Simple/Internals.hs b/GHC/Integer/Simple/Internals.hs new file mode 100644 index 0000000000000000000000000000000000000000..64d0d6fd7941d3dd88397b9ee07e5a079888056c --- /dev/null +++ b/GHC/Integer/Simple/Internals.hs @@ -0,0 +1,23 @@ + +{-# LANGUAGE NoImplicitPrelude #-} + +----------------------------------------------------------------------------- +-- | +-- Module : GHC.Integer.Simple.Internals +-- Copyright : (c) Ian Lynagh 2007-2008 +-- License : BSD3 +-- +-- Maintainer : igloo@earth.li +-- Stability : internal +-- Portability : non-portable (GHC Extensions) +-- +-- An simple definition of the 'Integer' type. +-- +----------------------------------------------------------------------------- + +module GHC.Integer.Simple.Internals ( + module GHC.Integer.Type + ) where + +import GHC.Integer.Type + diff --git a/GHC/Integer/Type.hs b/GHC/Integer/Type.hs new file mode 100644 index 0000000000000000000000000000000000000000..33a8cd85a7c55d0738e6b04aa619d82f4f2d6df4 --- /dev/null +++ b/GHC/Integer/Type.hs @@ -0,0 +1,51 @@ + +{-# LANGUAGE NoImplicitPrelude #-} + +----------------------------------------------------------------------------- +-- | +-- Module : GHC.Integer.Type +-- Copyright : (c) Ian Lynagh 2007-2008 +-- License : BSD3 +-- +-- Maintainer : igloo@earth.li +-- Stability : internal +-- Portability : non-portable (GHC Extensions) +-- +-- An simple definition of the 'Integer' type. +-- +----------------------------------------------------------------------------- + +#include "MachDeps.h" + +module GHC.Integer.Type ( + Integer(..), + Positive, Positives, + Digits(..), Digit, + List(..) + ) where + +import GHC.Prim + +#if !defined(__HADDOCK__) + +data Integer = Positive !Positive | Negative !Positive | Naught + +------------------------------------------------------------------- +-- The hard work is done on positive numbers + +-- Least significant bit is first + +-- Positive's have the property that they contain at least one Bit, +-- and their last Bit is One. +type Positive = Digits +type Positives = List Positive + +data Digits = Some !Digit !Digits + | None +type Digit = Word# + +-- XXX Could move [] above us +data List a = Nil | Cons a (List a) + +#endif + diff --git a/integer.cabal b/integer-simple.cabal similarity index 60% rename from integer.cabal rename to integer-simple.cabal index fff99f2736a90aaa48848f9df980d354a9d42630..b137dd8997830ff752e269eff2306864cccdb7ab 100644 --- a/integer.cabal +++ b/integer-simple.cabal @@ -1,4 +1,4 @@ -name: integer +name: integer-simple version: 0.1 license: BSD3 license-file: LICENSE @@ -12,9 +12,11 @@ build-type: Simple Library { build-depends: ghc-prim exposed-modules: GHC.Integer + GHC.Integer.Simple.Internals + other-modules: GHC.Integer.Type extensions: CPP, MagicHash, BangPatterns, UnboxedTuples, ForeignFunctionInterface, UnliftedFFITypes - -- We need to set the package name to integer (without a version number) - -- as it's magic. - ghc-options: -package-name integer -Wall -Werror + -- We need to set the package name to integer-simple + -- (without a version number) as it's magic. + ghc-options: -package-name integer-simple -Wall -Werror }