summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libraries/integer-gmp/GHC/Integer/Type.lhs87
1 files changed, 78 insertions, 9 deletions
diff --git a/libraries/integer-gmp/GHC/Integer/Type.lhs b/libraries/integer-gmp/GHC/Integer/Type.lhs
index fe4be9299f..a4f919fdb9 100644
--- a/libraries/integer-gmp/GHC/Integer/Type.lhs
+++ b/libraries/integer-gmp/GHC/Integer/Type.lhs
@@ -7,6 +7,15 @@
--
-- It gives an in-depth description of implementation details and
-- decisions.
+--
+-- TODO: Try to use optimized big/small int primops on IL32P64 archs
+-- (mostly Windows/x86_64). Currently, we have to fall back to
+-- unoptimized code-paths for most big/small-int primops, due to
+-- @mpz_*()@ functions using @long@ types, which is smaller than
+-- @mp_limb_t@ on IL32P64. The @mpn_*()@ functions are often safe to
+-- use, as they use @mb_limb_t@ instead of @long@.
+-- (look out for @#if SIZEOF_HSWORD == SIZEOF_LONG@ occurences)
+--
#include "MachDeps.h"
#if SIZEOF_HSWORD == 4
@@ -39,13 +48,11 @@ import GHC.Integer.GMP.Prim (
-- GMP-related primitives
MPZ#,
cmpInteger#, cmpIntegerInt#,
- plusInteger#, plusIntegerInt#, minusInteger#, minusIntegerInt#,
- timesInteger#, timesIntegerInt#,
- quotRemInteger#, quotRemIntegerWord#,
- quotInteger#, quotIntegerWord#, remInteger#, remIntegerWord#,
- divModInteger#, divModIntegerWord#,
- divInteger#, divIntegerWord#, modInteger#, modIntegerWord#,
- divExactInteger#, divExactIntegerWord#,
+ plusInteger#, minusInteger#,
+ timesInteger#,
+ quotRemInteger#, quotInteger#, remInteger#,
+ divModInteger#, divInteger#, modInteger#,
+ divExactInteger#,
gcdInteger#, gcdExtInteger#, gcdIntegerInt#, gcdInt#,
decodeDouble#,
int2Integer#, integer2Int#, word2Integer#, integer2Word#,
@@ -56,6 +63,15 @@ import GHC.Integer.GMP.Prim (
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#,
@@ -258,13 +274,17 @@ 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))
+ = 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) -- See Note [Use S# if possible]
@@ -280,6 +300,7 @@ divModInteger (S# i) (S# j) = (# S# d, S# m #)
-- evaluated strictly.
!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)
@@ -287,6 +308,9 @@ divModInteger (J# s1 d1) (S# b) | isTrue# (b <# 0#)
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)
@@ -303,10 +327,14 @@ remInteger ia@(S# a) (J# sb b)
| otherwise = S# (0# -# a)
-}
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)
@@ -321,10 +349,14 @@ quotInteger (S# a) (J# sb b)
| otherwise = S# 0
-}
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)
@@ -333,10 +365,14 @@ 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)
@@ -345,10 +381,14 @@ 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}
@@ -406,9 +446,13 @@ 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}
@@ -547,10 +591,18 @@ 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)
@@ -559,24 +611,41 @@ 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 (J# s1 d1) (S# j) = mpzToInteger (minusIntegerInt# s1 d1 j)
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)
{-# NOINLINE timesInteger #-}
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 -- swap args & retry
timesInteger (J# s1 d1) (J# s2 d2) = mpzToInteger (timesInteger# s1 d1 s2 d2)