Add divInteger and modInteger functions
authorIan Lynagh <igloo@earth.li>
Tue, 19 Jun 2012 18:33:43 +0000 (19:33 +0100)
committerIan Lynagh <igloo@earth.li>
Tue, 19 Jun 2012 18:55:04 +0000 (19:55 +0100)
Now that divModInteger isn't inlined, we were getting allocations for
both results even if we're just going to throw one away.

GHC/Integer.lhs
GHC/Integer/GMP/Prim.hs
GHC/Integer/Type.lhs
cbits/gmp-wrappers.cmm

index bc61d03..57a97e1 100644 (file)
@@ -27,7 +27,8 @@ module GHC.Integer (
     plusInteger, minusInteger, timesInteger, negateInteger,
     eqInteger, neqInteger, absInteger, signumInteger,
     leInteger, gtInteger, ltInteger, geInteger, compareInteger,
-    divModInteger, quotRemInteger, quotInteger, remInteger,
+    divModInteger, divInteger, modInteger,
+    quotRemInteger, quotInteger, remInteger,
     encodeFloatInteger, floatFromInteger,
     encodeDoubleInteger, decodeDoubleInteger, doubleFromInteger,
     -- gcdInteger, lcmInteger,
index 8de4a8b..354d55f 100644 (file)
@@ -16,6 +16,8 @@ module GHC.Integer.GMP.Prim (
     quotInteger#,
     remInteger#,
     divModInteger#,
+    divInteger#,
+    modInteger#,
     divExactInteger#,
 
     gcdInteger#,
@@ -101,6 +103,10 @@ foreign import prim "integer_cmm_remIntegerzh" remInteger#
 --
 foreign import prim "integer_cmm_divModIntegerzh" divModInteger#
   :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray#, Int#, ByteArray# #)
+foreign import prim "integer_cmm_divIntegerzh" divInteger#
+  :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
+foreign import prim "integer_cmm_modIntegerzh" modInteger#
+  :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
 
 -- | Divisor is guaranteed to be a factor of dividend.
 --
index 44cc076..be3ebea 100644 (file)
@@ -31,7 +31,8 @@ import GHC.Integer.GMP.Prim (
     -- GMP-related primitives
     cmpInteger#, cmpIntegerInt#,
     plusInteger#, minusInteger#, timesInteger#,
-    quotRemInteger#, quotInteger#, remInteger#, divModInteger#,
+    quotRemInteger#, quotInteger#, remInteger#,
+    divModInteger#, divInteger#, modInteger#,
     gcdInteger#, gcdIntegerInt#, gcdInt#, divExactInteger#,
     decodeDouble#,
     int2Integer#, integer2Int#, word2Integer#, integer2Word#,
@@ -232,6 +233,29 @@ quotInteger (J# sa a) (S# 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
+
+{-# NOINLINE modInteger #-}
+modInteger :: Integer -> Integer -> Integer
+modInteger a@(S# INT_MINBOUND) b = modInteger (toBig a) b
+modInteger (S# a) (S# b) = S# (modInt# a b)
+modInteger ia@(S# _) ib@(J# _ _) = modInteger (toBig ia) ib
+modInteger (J# sa a) (S# b)
+  = case int2Integer# b of { (# sb, b' #) ->
+    case modInteger# sa a sb b' of { (# sr, r #) ->
+    S# (integer2Int# sr r) }}
+modInteger (J# sa a) (J# sb b)
+  = case modInteger# sa a sb b of (# sr, r #) -> J# sr r
+
+{-# NOINLINE divInteger #-}
+divInteger :: Integer -> Integer -> Integer
+divInteger a@(S# INT_MINBOUND) b = divInteger (toBig a) b
+divInteger (S# a) (S# b) = S# (divInt# a b)
+divInteger ia@(S# _) ib@(J# _ _) = divInteger (toBig ia) ib
+divInteger (J# sa a) (S# b)
+  = case int2Integer# b of { (# sb, b' #) ->
+    case divInteger# sa a sb b' of (# sq, q #) -> J# sq q }
+divInteger (J# sa a) (J# sb b)
+  = case divInteger# sa a sb b of (# sg, g #) -> J# sg g
 \end{code}
 
 
index 43df337..145e6de 100644 (file)
@@ -377,6 +377,8 @@ GMP_TAKE2_RET1(integer_cmm_timesIntegerzh,    __gmpz_mul)
 GMP_TAKE2_RET1(integer_cmm_gcdIntegerzh,      __gmpz_gcd)
 GMP_TAKE2_RET1(integer_cmm_quotIntegerzh,     __gmpz_tdiv_q)
 GMP_TAKE2_RET1(integer_cmm_remIntegerzh,      __gmpz_tdiv_r)
+GMP_TAKE2_RET1(integer_cmm_divIntegerzh,      __gmpz_fdiv_q)
+GMP_TAKE2_RET1(integer_cmm_modIntegerzh,      __gmpz_fdiv_r)
 GMP_TAKE2_RET1(integer_cmm_divExactIntegerzh, __gmpz_divexact)
 GMP_TAKE2_RET1(integer_cmm_andIntegerzh,      __gmpz_and)
 GMP_TAKE2_RET1(integer_cmm_orIntegerzh,       __gmpz_ior)