\begin{code}
#include "MachDeps.h"
#if SIZEOF_HSWORD == 4
#define INT_MINBOUND (-2147483648#)
#define NEG_INT_MINBOUND (S# 2147483647# `plusInteger` S# 1#)
#elif SIZEOF_HSWORD == 8
#define INT_MINBOUND (-9223372036854775808#)
#define NEG_INT_MINBOUND (S# 9223372036854775807# `plusInteger` S# 1#)
#else
#error Unknown SIZEOF_HSWORD; can't define INT_MINBOUND and NEG_INT_MINBOUND
#endif
module GHC.Integer.Type where
import GHC.Prim (
Int#, Word#, Double#, Float#, ByteArray#, MutableByteArray#, Addr#, State#,
indexIntArray#,
int2Word#, int2Double#, int2Float#, word2Int#,
quotInt#, remInt#, quotRemInt#, negateInt#,
(*#), (-#),
(==#), (/=#), (<=#), (>=#), (<#), (>#),
mulIntMayOflo#, addIntC#, subIntC#,
and#, or#, xor#,
)
import GHC.Integer.GMP.Prim (
MPZ#,
cmpInteger#, cmpIntegerInt#,
plusInteger#, minusInteger#,
timesInteger#,
quotRemInteger#, quotInteger#, remInteger#,
divModInteger#, divInteger#, modInteger#,
divExactInteger#,
gcdInteger#, gcdExtInteger#, gcdIntegerInt#, gcdInt#,
decodeDouble#,
int2Integer#, integer2Int#, word2Integer#, integer2Word#,
andInteger#, orInteger#, xorInteger#, complementInteger#,
testBitInteger#, mul2ExpInteger#, fdivQ2ExpInteger#,
powInteger#, powModInteger#, powModSecInteger#, recipModInteger#,
nextPrimeInteger#, testPrimeInteger#,
sizeInBaseInteger#,
importIntegerFromByteArray#, importIntegerFromAddr#,
exportIntegerToMutableByteArray#, exportIntegerToAddr#,
#if SIZEOF_HSWORD == SIZEOF_LONG
plusIntegerInt#, minusIntegerInt#,
timesIntegerInt#,
divIntegerWord#, modIntegerWord#, divModIntegerWord#,
divExactIntegerWord#,
quotIntegerWord#, remIntegerWord#, quotRemIntegerWord#,
#endif
#if WORD_SIZE_IN_BITS < 64
int64ToInteger#, integerToInt64#,
word64ToInteger#, integerToWord64#,
#endif
)
#if WORD_SIZE_IN_BITS < 64
import GHC.IntWord64 (
Int64#, Word64#,
int64ToWord64#, intToInt64#,
int64ToInt#, word64ToInt64#,
geInt64#, leInt64#, leWord64#,
)
#endif
import GHC.Classes
import GHC.Types
default ()
\end{code}
%*********************************************************
%* *
\subsection{The @Integer@ type}
%* *
%*********************************************************
Convenient boxed Integer PrimOps.
\begin{code}
data Integer
= S# Int#
| J# Int# ByteArray#
mkInteger :: Bool
-> [Int]
-> Integer
mkInteger nonNegative is = let abs = f is
in if nonNegative then abs else negateInteger abs
where f [] = S# 0#
f (I# i : is') = S# i `orInteger` shiftLInteger (f is') 31#
smallInteger :: Int# -> Integer
smallInteger i = S# i
wordToInteger :: Word# -> Integer
wordToInteger w = if isTrue# (i >=# 0#)
then S# i
else case word2Integer# w of (# s, d #) -> J# s d
where
!i = word2Int# w
integerToWord :: Integer -> Word#
integerToWord (S# i) = int2Word# i
integerToWord (J# s d) = integer2Word# s d
#if WORD_SIZE_IN_BITS < 64
integerToWord64 :: Integer -> Word64#
integerToWord64 (S# i) = int64ToWord64# (intToInt64# i)
integerToWord64 (J# s d) = integerToWord64# s d
word64ToInteger :: Word64# -> Integer
word64ToInteger w = if isTrue# (w `leWord64#` int64ToWord64# (intToInt64# 0x7FFFFFFF#))
then S# (int64ToInt# (word64ToInt64# w))
else case word64ToInteger# w of
(# s, d #) -> J# s d
integerToInt64 :: Integer -> Int64#
integerToInt64 (S# i) = intToInt64# i
integerToInt64 (J# s d) = integerToInt64# s d
int64ToInteger :: Int64# -> Integer
int64ToInteger i = if isTrue# (i `leInt64#` intToInt64# 0x7FFFFFFF#) &&
isTrue# (i `geInt64#` intToInt64# 0x80000000#)
then smallInteger (int64ToInt# i)
else case int64ToInteger# i of
(# s, d #) -> J# s d
#endif
integerToInt :: Integer -> Int#
integerToInt (S# i) = i
integerToInt (J# s d) = integer2Int# s d
minIntAsBig :: Integer
minIntAsBig = case int2Integer# INT_MINBOUND of { (# s, d #) -> J# s d }
toBig :: Integer -> Integer
toBig (S# i) = case int2Integer# i of { (# s, d #) -> J# s d }
toBig i@(J# _ _) = i
toSmall :: Integer -> Integer
toSmall i@(S# _) = i
toSmall (J# s# mb#) = smartJ# s# mb#
smartJ# :: Int# -> ByteArray# -> Integer
smartJ# 0# _ = S# 0#
smartJ# 1# mb# | isTrue# (v ># 0#) = S# v
where
v = indexIntArray# mb# 0#
smartJ# (1#) mb# | isTrue# (v <# 0#) = S# v
where
v = negateInt# (indexIntArray# mb# 0#)
smartJ# s# mb# = J# s# mb#
mpzToInteger :: MPZ# -> Integer
mpzToInteger (# 0#, _, _ #) = S# 0#
mpzToInteger (# 1#, _, w# #) | isTrue# (v# >=# 0#) = S# v#
| True = case word2Integer# w# of (# _, d #) -> J# 1# d
where
v# = word2Int# w#
mpzToInteger (# 1#, _, w# #) | isTrue# (v# <=# 0#) = S# v#
| True = case word2Integer# w# of (# _, d #) -> J# 1# d
where
v# = negateInt# (word2Int# w#)
mpzToInteger (# s#, mb#, _ #) = J# s# mb#
mpzToInteger2 :: (# MPZ#, MPZ# #) -> (# Integer, Integer #)
mpzToInteger2 (# mpz1, mpz2 #) = (# i1, i2 #)
where
!i1 = mpzToInteger mpz1
!i2 = mpzToInteger mpz2
mpzNeg :: MPZ# -> MPZ#
mpzNeg (# s#, mb#, w# #) = (# negateInt# s#, mb#, w# #)
\end{code}
Note [Use S# if possible]
~~~~~~~~~~~~~~~~~~~~~~~~~
It's a big win to use S#, rather than J#, whenever possible. Not only
does it take less space, but (probably more important) subsequent
operations are more efficient. See Trac #8638.
'smartJ#' is the smart constructor for J# that performs the necessary
tests. When returning a nested result, we always use smartJ# strictly,
thus
let !r = smartJ# a b in (# r, somthing_else #)
to avoid creating a thunk that is subsequently evaluated to a J#.
smartJ# itself does a pretty small amount of work, so it's not worth
thunking it.
We call 'smartJ#' in places like quotRemInteger where a big input
might produce a small output.
Just using smartJ# in this way has good results:
Program Size Allocs Runtime Elapsed TotalMem
--------------------------------------------------------------------------------
gamteb +0.1% -19.0% 0.03 0.03 +0.0%
kahan +0.2% -1.2% 0.17 0.17 +0.0%
mandel +0.1% -7.7% 0.05 0.05 +0.0%
power +0.1% -40.8% -32.5% -32.5% +0.0%
symalg +0.2% -0.5% 0.01 0.01 +0.0%
--------------------------------------------------------------------------------
Min +0.0% -40.8% -32.5% -32.5% -5.1%
Max +0.2% +0.1% +2.0% +2.0% +0.0%
Geometric Mean +0.1% -1.0% -2.5% -2.5% -0.1%
%*********************************************************
%* *
\subsection{Dividing @Integers@}
%* *
%*********************************************************
\begin{code}
quotRemInteger :: Integer -> Integer -> (# Integer, Integer #)
quotRemInteger (S# INT_MINBOUND) b = quotRemInteger minIntAsBig b
quotRemInteger (S# i) (S# j) = case quotRemInt# i j of
(# q, r #) -> (# S# q, S# r #)
#if SIZEOF_HSWORD == SIZEOF_LONG
quotRemInteger (J# s1 d1) (S# b) | isTrue# (b <# 0#)
= case quotRemIntegerWord# s1 d1 (int2Word# (negateInt# b)) of
(# q, r #) -> let !q' = mpzToInteger(mpzNeg q)
!r' = mpzToInteger(mpzNeg r)
in (# q', r' #)
quotRemInteger (J# s1 d1) (S# b)
= mpzToInteger2 (quotRemIntegerWord# s1 d1 (int2Word# b))
#else
quotRemInteger i1@(J# _ _) i2@(S# _) = quotRemInteger i1 (toBig i2)
#endif
quotRemInteger i1@(S# _) i2@(J# _ _) = quotRemInteger (toBig i1) i2
quotRemInteger (J# s1 d1) (J# s2 d2)
= mpzToInteger2(quotRemInteger# s1 d1 s2 d2)
divModInteger :: Integer -> Integer -> (# Integer, Integer #)
divModInteger (S# INT_MINBOUND) b = divModInteger minIntAsBig b
divModInteger (S# i) (S# j) = (# S# d, S# m #)
where
!d = i `divInt#` j
!m = i `modInt#` j
#if SIZEOF_HSWORD == SIZEOF_LONG
divModInteger (J# s1 d1) (S# b) | isTrue# (b <# 0#)
= case divModIntegerWord# (negateInt# s1) d1 (int2Word# (negateInt# b)) of
(# q, r #) -> let !q' = mpzToInteger (mpzNeg q)
!r' = mpzToInteger r
in (# q', r' #)
divModInteger (J# s1 d1) (S# b)
= mpzToInteger2(divModIntegerWord# s1 d1 (int2Word# b))
#else
divModInteger i1@(J# _ _) i2@(S# _) = divModInteger i1 (toBig i2)
#endif
divModInteger i1@(S# _) i2@(J# _ _) = divModInteger (toBig i1) i2
divModInteger (J# s1 d1) (J# s2 d2) = mpzToInteger2 (divModInteger# s1 d1 s2 d2)
remInteger :: Integer -> Integer -> Integer
remInteger (S# INT_MINBOUND) b = remInteger minIntAsBig b
remInteger (S# a) (S# b) = S# (remInt# a b)
remInteger ia@(S# _) ib@(J# _ _) = remInteger (toBig ia) ib
#if SIZEOF_HSWORD == SIZEOF_LONG
remInteger (J# sa a) (S# b)
= mpzToInteger (remIntegerWord# sa a w)
where
w = int2Word# (if isTrue# (b <# 0#) then negateInt# b else b)
#else
remInteger i1@(J# _ _) i2@(S# _) = remInteger i1 (toBig i2)
#endif
remInteger (J# sa a) (J# sb b)
= mpzToInteger (remInteger# sa a sb b)
quotInteger :: Integer -> Integer -> Integer
quotInteger (S# INT_MINBOUND) b = quotInteger minIntAsBig b
quotInteger (S# a) (S# b) = S# (quotInt# a b)
quotInteger ia@(S# _) ib@(J# _ _) = quotInteger (toBig ia) ib
#if SIZEOF_HSWORD == SIZEOF_LONG
quotInteger (J# sa a) (S# b) | isTrue# (b <# 0#)
= mpzToInteger (mpzNeg (quotIntegerWord# sa a (int2Word# (negateInt# b))))
quotInteger (J# sa a) (S# b)
= mpzToInteger (quotIntegerWord# sa a (int2Word# b))
#else
quotInteger i1@(J# _ _) i2@(S# _) = quotInteger i1 (toBig i2)
#endif
quotInteger (J# sa a) (J# sb b)
= mpzToInteger (quotInteger# sa a sb b)
modInteger :: Integer -> Integer -> Integer
modInteger (S# INT_MINBOUND) b = modInteger minIntAsBig b
modInteger (S# a) (S# b) = S# (modInt# a b)
modInteger ia@(S# _) ib@(J# _ _) = modInteger (toBig ia) ib
#if SIZEOF_HSWORD == SIZEOF_LONG
modInteger (J# sa a) (S# b) | isTrue# (b <# 0#)
= mpzToInteger (mpzNeg (remIntegerWord# (negateInt# sa) a (int2Word# (negateInt# b))))
modInteger (J# sa a) (S# b)
= mpzToInteger (modIntegerWord# sa a (int2Word# b))
#else
modInteger i1@(J# _ _) i2@(S# _) = modInteger i1 (toBig i2)
#endif
modInteger (J# sa a) (J# sb b)
= mpzToInteger (modInteger# sa a sb b)
divInteger :: Integer -> Integer -> Integer
divInteger (S# INT_MINBOUND) b = divInteger minIntAsBig b
divInteger (S# a) (S# b) = S# (divInt# a b)
divInteger ia@(S# _) ib@(J# _ _) = divInteger (toBig ia) ib
#if SIZEOF_HSWORD == SIZEOF_LONG
divInteger (J# sa a) (S# b) | isTrue# (b <# 0#)
= mpzToInteger (divIntegerWord# (negateInt# sa) a (int2Word# (negateInt# b)))
divInteger (J# sa a) (S# b)
= mpzToInteger (divIntegerWord# sa a (int2Word# b))
#else
divInteger i1@(J# _ _) i2@(S# _) = divInteger i1 (toBig i2)
#endif
divInteger (J# sa a) (J# sb b)
= mpzToInteger (divInteger# sa a sb b)
\end{code}
\begin{code}
gcdInteger :: Integer -> Integer -> Integer
gcdInteger (S# INT_MINBOUND) b = gcdInteger minIntAsBig b
gcdInteger a (S# INT_MINBOUND) = gcdInteger a minIntAsBig
gcdInteger (S# a) (S# b) = S# (gcdInt a b)
gcdInteger ia@(S# a) ib@(J# sb b)
= if isTrue# (a ==# 0#) then absInteger ib
else if isTrue# (sb ==# 0#) then absInteger ia
else S# (gcdIntegerInt# absSb b absA)
where !absA = if isTrue# (a <# 0#) then negateInt# a else a
!absSb = if isTrue# (sb <# 0#) then negateInt# sb else sb
gcdInteger ia@(J# _ _) ib@(S# _) = gcdInteger ib ia
gcdInteger (J# sa a) (J# sb b) = mpzToInteger (gcdInteger# sa a sb b)
gcdExtInteger :: Integer -> Integer -> (# Integer, Integer #)
gcdExtInteger a@(S# _) b@(S# _) = gcdExtInteger (toBig a) (toBig b)
gcdExtInteger a@(S# _) b@(J# _ _) = gcdExtInteger (toBig a) b
gcdExtInteger a@(J# _ _) b@(S# _) = gcdExtInteger a (toBig b)
gcdExtInteger (J# sa a) (J# sb b) = mpzToInteger2 (gcdExtInteger# sa a sb b)
lcmInteger :: Integer -> Integer -> Integer
lcmInteger a b = if a `eqInteger` S# 0# then S# 0#
else if b `eqInteger` S# 0# then S# 0#
else (divExact aa (gcdInteger aa ab)) `timesInteger` ab
where aa = absInteger a
ab = absInteger b
gcdInt :: Int# -> Int# -> Int#
gcdInt 0# y = absInt y
gcdInt x 0# = absInt x
gcdInt x y = gcdInt# (absInt x) (absInt y)
absInt :: Int# -> Int#
absInt x = if isTrue# (x <# 0#) then negateInt# x else x
divExact :: Integer -> Integer -> Integer
divExact (S# INT_MINBOUND) b = divExact minIntAsBig b
divExact (S# a) (S# b) = S# (quotInt# a b)
divExact (S# a) (J# sb b)
= S# (quotInt# a (integer2Int# sb b))
#if SIZEOF_HSWORD == SIZEOF_LONG
divExact (J# sa a) (S# b) | isTrue# (b <# 0#)
= mpzToInteger (divExactIntegerWord# (negateInt# sa) a (int2Word# (negateInt# b)))
divExact (J# sa a) (S# b) = mpzToInteger (divExactIntegerWord# sa a (int2Word# b))
#else
divExact i1@(J# _ _) i2@(S# _) = divExact i1 (toBig i2)
#endif
divExact (J# sa a) (J# sb b) = mpzToInteger (divExactInteger# sa a sb b)
\end{code}
%*********************************************************
%* *
\subsection{The @Integer@ instances for @Eq@, @Ord@}
%* *
%*********************************************************
\begin{code}
eqInteger# :: Integer -> Integer -> Int#
eqInteger# (S# i) (S# j) = i ==# j
eqInteger# (S# i) (J# s d) = cmpIntegerInt# s d i ==# 0#
eqInteger# (J# s d) (S# i) = cmpIntegerInt# s d i ==# 0#
eqInteger# (J# s1 d1) (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) ==# 0#
neqInteger# :: Integer -> Integer -> Int#
neqInteger# (S# i) (S# j) = i /=# j
neqInteger# (S# i) (J# s d) = cmpIntegerInt# s d i /=# 0#
neqInteger# (J# s d) (S# i) = cmpIntegerInt# s d i /=# 0#
neqInteger# (J# s1 d1) (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) /=# 0#
eqInteger, neqInteger :: Integer -> Integer -> Bool
eqInteger a b = isTrue# (a `eqInteger#` b)
neqInteger a b = isTrue# (a `neqInteger#` b)
instance Eq Integer where
(==) = eqInteger
(/=) = neqInteger
leInteger# :: Integer -> Integer -> Int#
leInteger# (S# i) (S# j) = i <=# j
leInteger# (J# s d) (S# i) = cmpIntegerInt# s d i <=# 0#
leInteger# (S# i) (J# s d) = cmpIntegerInt# s d i >=# 0#
leInteger# (J# s1 d1) (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) <=# 0#
gtInteger# :: Integer -> Integer -> Int#
gtInteger# (S# i) (S# j) = i ># j
gtInteger# (J# s d) (S# i) = cmpIntegerInt# s d i ># 0#
gtInteger# (S# i) (J# s d) = cmpIntegerInt# s d i <# 0#
gtInteger# (J# s1 d1) (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) ># 0#
ltInteger# :: Integer -> Integer -> Int#
ltInteger# (S# i) (S# j) = i <# j
ltInteger# (J# s d) (S# i) = cmpIntegerInt# s d i <# 0#
ltInteger# (S# i) (J# s d) = cmpIntegerInt# s d i ># 0#
ltInteger# (J# s1 d1) (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) <# 0#
geInteger# :: Integer -> Integer -> Int#
geInteger# (S# i) (S# j) = i >=# j
geInteger# (J# s d) (S# i) = cmpIntegerInt# s d i >=# 0#
geInteger# (S# i) (J# s d) = cmpIntegerInt# s d i <=# 0#
geInteger# (J# s1 d1) (J# s2 d2) = (cmpInteger# s1 d1 s2 d2) >=# 0#
leInteger, gtInteger, ltInteger, geInteger :: Integer -> Integer -> Bool
leInteger a b = isTrue# (a `leInteger#` b)
gtInteger a b = isTrue# (a `gtInteger#` b)
ltInteger a b = isTrue# (a `ltInteger#` b)
geInteger a b = isTrue# (a `geInteger#` b)
compareInteger :: Integer -> Integer -> Ordering
compareInteger (S# i) (S# j)
= if isTrue# (i ==# j) then EQ
else if isTrue# (i <=# j) then LT
else GT
compareInteger (J# s d) (S# i)
= case cmpIntegerInt# s d i of { res# ->
if isTrue# (res# <# 0#) then LT else
if isTrue# (res# ># 0#) then GT else EQ
}
compareInteger (S# i) (J# s d)
= case cmpIntegerInt# s d i of { res# ->
if isTrue# (res# ># 0#) then LT else
if isTrue# (res# <# 0#) then GT else EQ
}
compareInteger (J# s1 d1) (J# s2 d2)
= case cmpInteger# s1 d1 s2 d2 of { res# ->
if isTrue# (res# <# 0#) then LT else
if isTrue# (res# ># 0#) then GT else EQ
}
instance Ord Integer where
(<=) = leInteger
(<) = ltInteger
(>) = gtInteger
(>=) = geInteger
compare = compareInteger
\end{code}
%*********************************************************
%* *
\subsection{The @Integer@ instances for @Num@}
%* *
%*********************************************************
\begin{code}
absInteger :: Integer -> Integer
absInteger (S# INT_MINBOUND) = NEG_INT_MINBOUND
absInteger n@(S# i) = if isTrue# (i >=# 0#) then n else S# (negateInt# i)
absInteger n@(J# s d) = if isTrue# (s >=# 0#) then n else J# (negateInt# s) d
signumInteger :: Integer -> Integer
signumInteger (S# i) = if isTrue# (i <# 0#) then S# 1#
else if isTrue# (i ==# 0#) then S# 0#
else S# 1#
signumInteger (J# s d)
= let
!cmp = cmpIntegerInt# s d 0#
in
if isTrue# (cmp ># 0#) then S# 1#
else if isTrue# (cmp ==# 0#) then S# 0#
else S# (negateInt# 1#)
plusInteger :: Integer -> Integer -> Integer
plusInteger (S# i) (S# j) = case addIntC# i j of
(# r, c #) ->
if isTrue# (c ==# 0#)
then S# r
#if SIZEOF_HSWORD == SIZEOF_LONG
else case int2Integer# i of
(# s, d #) -> mpzToInteger (plusIntegerInt# s d j)
#else
else plusInteger (toBig (S# i)) (toBig (S# j))
#endif
plusInteger i1@(J# _ _) (S# 0#) = i1
#if SIZEOF_HSWORD == SIZEOF_LONG
plusInteger (J# s1 d1) (S# j) = mpzToInteger (plusIntegerInt# s1 d1 j)
#else
plusInteger i1@(J# _ _) i2@(S# _) = plusInteger i1 (toBig i2)
#endif
plusInteger i1@(S# _) i2@(J# _ _) = plusInteger i2 i1
plusInteger (J# s1 d1) (J# s2 d2) = mpzToInteger (plusInteger# s1 d1 s2 d2)
minusInteger :: Integer -> Integer -> Integer
minusInteger (S# i) (S# j) = case subIntC# i j of
(# r, c #) ->
if isTrue# (c ==# 0#) then S# r
#if SIZEOF_HSWORD == SIZEOF_LONG
else case int2Integer# i of
(# s, d #) -> mpzToInteger (minusIntegerInt# s d j)
#else
else minusInteger (toBig (S# i)) (toBig (S# j))
#endif
minusInteger i1@(J# _ _) (S# 0#) = i1
minusInteger (S# 0#) (J# s2 d2) = J# (negateInt# s2) d2
#if SIZEOF_HSWORD == SIZEOF_LONG
minusInteger (J# s1 d1) (S# j) = mpzToInteger (minusIntegerInt# s1 d1 j)
minusInteger (S# i) (J# s2 d2) = mpzToInteger (plusIntegerInt# (negateInt# s2) d2 i)
#else
minusInteger i1@(J# _ _) i2@(S# _) = minusInteger i1 (toBig i2)
minusInteger i1@(S# _) i2@(J# _ _) = minusInteger (toBig i1) i2
#endif
minusInteger (J# s1 d1) (J# s2 d2) = mpzToInteger (minusInteger# s1 d1 s2 d2)
timesInteger :: Integer -> Integer -> Integer
timesInteger (S# i) (S# j) = if isTrue# (mulIntMayOflo# i j ==# 0#)
then S# (i *# j)
#if SIZEOF_HSWORD == SIZEOF_LONG
else case int2Integer# i of
(# s, d #) -> mpzToInteger (timesIntegerInt# s d j)
#else
else timesInteger (toBig (S# i)) (toBig (S# j))
#endif
timesInteger (S# 0#) _ = S# 0#
timesInteger (S# 1#) i2 = negateInteger i2
timesInteger (S# 1#) i2 = i2
#if SIZEOF_HSWORD == SIZEOF_LONG
timesInteger (S# i1) (J# s2 d2) = mpzToInteger (timesIntegerInt# s2 d2 i1)
#else
timesInteger i1@(S# _) i2@(J# _ _) = timesInteger (toBig i1) i2
#endif
timesInteger i1@(J# _ _) i2@(S# _) = timesInteger i2 i1
timesInteger (J# s1 d1) (J# s2 d2) = mpzToInteger (timesInteger# s1 d1 s2 d2)
negateInteger :: Integer -> Integer
negateInteger (S# INT_MINBOUND) = NEG_INT_MINBOUND
negateInteger (S# i) = S# (negateInt# i)
negateInteger (J# s d) = J# (negateInt# s) d
\end{code}
%*********************************************************
%* *
\subsection{The @Integer@ stuff for Double@}
%* *
%*********************************************************
\begin{code}
encodeFloatInteger :: Integer -> Int# -> Float#
encodeFloatInteger (S# i) j = int_encodeFloat# i j
encodeFloatInteger (J# s# d#) e = encodeFloat# s# d# e
encodeDoubleInteger :: Integer -> Int# -> Double#
encodeDoubleInteger (S# i) j = int_encodeDouble# i j
encodeDoubleInteger (J# s# d#) e = encodeDouble# s# d# e
decodeDoubleInteger :: Double# -> (# Integer, Int# #)
decodeDoubleInteger d = case decodeDouble# d of
(# exp#, man# #) -> let !man = mpzToInteger man#
in (# man, exp# #)
doubleFromInteger :: Integer -> Double#
doubleFromInteger (S# i#) = int2Double# i#
doubleFromInteger (J# s# d#) = encodeDouble# s# d# 0#
floatFromInteger :: Integer -> Float#
floatFromInteger (S# i#) = int2Float# i#
floatFromInteger (J# s# d#) = encodeFloat# s# d# 0#
foreign import ccall unsafe "integer_cbits_encodeFloat"
encodeFloat# :: Int# -> ByteArray# -> Int# -> Float#
foreign import ccall unsafe "__int_encodeFloat"
int_encodeFloat# :: Int# -> Int# -> Float#
foreign import ccall unsafe "integer_cbits_encodeDouble"
encodeDouble# :: Int# -> ByteArray# -> Int# -> Double#
foreign import ccall unsafe "__int_encodeDouble"
int_encodeDouble# :: Int# -> Int# -> Double#
\end{code}
%*********************************************************
%* *
\subsection{The @Integer@ Bit definitions@}
%* *
%*********************************************************
We explicitly pattern match against J# and S# in order to produce
Core that doesn't have pattern matching errors, as that would
introduce a spurious dependency to base.
\begin{code}
andInteger :: Integer -> Integer -> Integer
(S# x) `andInteger` (S# y) = S# (word2Int# (int2Word# x `and#` int2Word# y))
x@(S# _) `andInteger` y@(J# _ _) = toBig x `andInteger` y
x@(J# _ _) `andInteger` y@(S# _) = x `andInteger` toBig y
(J# s1 d1) `andInteger` (J# s2 d2) =
mpzToInteger (andInteger# s1 d1 s2 d2)
orInteger :: Integer -> Integer -> Integer
(S# x) `orInteger` (S# y) = S# (word2Int# (int2Word# x `or#` int2Word# y))
x@(S# _) `orInteger` y@(J# _ _) = toBig x `orInteger` y
x@(J# _ _) `orInteger` y@(S# _) = x `orInteger` toBig y
(J# s1 d1) `orInteger` (J# s2 d2) =
mpzToInteger (orInteger# s1 d1 s2 d2)
xorInteger :: Integer -> Integer -> Integer
(S# x) `xorInteger` (S# y) = S# (word2Int# (int2Word# x `xor#` int2Word# y))
x@(S# _) `xorInteger` y@(J# _ _) = toBig x `xorInteger` y
x@(J# _ _) `xorInteger` y@(S# _) = x `xorInteger` toBig y
(J# s1 d1) `xorInteger` (J# s2 d2) =
mpzToInteger (xorInteger# s1 d1 s2 d2)
complementInteger :: Integer -> Integer
complementInteger (S# x)
= S# (word2Int# (int2Word# x `xor#` int2Word# (0# -# 1#)))
complementInteger (J# s d)
= mpzToInteger (complementInteger# s d)
shiftLInteger :: Integer -> Int# -> Integer
shiftLInteger j@(S# _) i = shiftLInteger (toBig j) i
shiftLInteger (J# s d) i = mpzToInteger (mul2ExpInteger# s d i)
shiftRInteger :: Integer -> Int# -> Integer
shiftRInteger j@(S# _) i = shiftRInteger (toBig j) i
shiftRInteger (J# s d) i = mpzToInteger (fdivQ2ExpInteger# s d i)
testBitInteger :: Integer -> Int# -> Bool
testBitInteger j@(S# _) i = testBitInteger (toBig j) i
testBitInteger (J# s d) i = isTrue# (testBitInteger# s d i /=# 0#)
powInteger :: Integer -> Word# -> Integer
powInteger j@(S# _) e = powInteger (toBig j) e
powInteger (J# s d) e = mpzToInteger (powInteger# s d e)
powModInteger :: Integer -> Integer -> Integer -> Integer
powModInteger (J# s1 d1) (J# s2 d2) (J# s3 d3) =
mpzToInteger (powModInteger# s1 d1 s2 d2 s3 d3)
powModInteger b e m = powModInteger (toBig b) (toBig e) (toBig m)
powModSecInteger :: Integer -> Integer -> Integer -> Integer
powModSecInteger (J# s1 d1) (J# s2 d2) (J# s3 d3) =
mpzToInteger (powModSecInteger# s1 d1 s2 d2 s3 d3)
powModSecInteger b e m = powModSecInteger (toBig b) (toBig e) (toBig m)
recipModInteger :: Integer -> Integer -> Integer
recipModInteger j@(S# _) m@(S# _) = recipModInteger (toBig j) (toBig m)
recipModInteger j@(S# _) m@(J# _ _) = recipModInteger (toBig j) m
recipModInteger j@(J# _ _) m@(S# _) = recipModInteger j (toBig m)
recipModInteger (J# s d) (J# ms md) = mpzToInteger (recipModInteger# s d ms md)
testPrimeInteger :: Integer -> Int# -> Int#
testPrimeInteger j@(S# _) reps = testPrimeInteger (toBig j) reps
testPrimeInteger (J# s d) reps = testPrimeInteger# s d reps
nextPrimeInteger :: Integer -> Integer
nextPrimeInteger j@(S# _) = nextPrimeInteger (toBig j)
nextPrimeInteger (J# s d) = mpzToInteger (nextPrimeInteger# s d)
sizeInBaseInteger :: Integer -> Int# -> Word#
sizeInBaseInteger (J# s d) b = sizeInBaseInteger# s d b
sizeInBaseInteger j@(S# _) b = sizeInBaseInteger (toBig j) b
exportIntegerToMutableByteArray :: Integer -> MutableByteArray# s -> Word# -> Int# -> State# s -> (# State# s, Word# #)
exportIntegerToMutableByteArray (J# s d) mba o e = exportIntegerToMutableByteArray# s d mba o e
exportIntegerToMutableByteArray j@(S# _) mba o e = exportIntegerToMutableByteArray (toBig j) mba o e
exportIntegerToAddr :: Integer -> Addr# -> Int# -> State# s -> (# State# s, Word# #)
exportIntegerToAddr (J# s d) addr o e = exportIntegerToAddr# s d addr o e
exportIntegerToAddr j@(S# _) addr o e = exportIntegerToAddr (toBig j) addr o e
importIntegerFromByteArray :: ByteArray# -> Word# -> Word# -> Int# -> Integer
importIntegerFromByteArray ba o l e = mpzToInteger (importIntegerFromByteArray# ba o l e)
importIntegerFromAddr :: Addr# -> Word# -> Int# -> State# s -> (# State# s, Integer #)
importIntegerFromAddr addr l e st = case importIntegerFromAddr# addr l e st of
(# st', mpz #) -> let !j = mpzToInteger mpz in (# st', j #)
\end{code}
%*********************************************************
%* *
\subsection{The @Integer@ hashing@}
%* *
%*********************************************************
\begin{code}
hashInteger :: Integer -> Int#
hashInteger = integerToInt
\end{code}