[commit: packages/integer-gmp] master: Expose GMP's `mpz_gcdext()` as internal primitive (ce8ec96)

git at git.haskell.org git
Tue Oct 1 10:07:52 UTC 2013


Repository : ssh://git at git.haskell.org/integer-gmp

On branch  : master
Link       : http://git.haskell.org/packages/integer-gmp.git/commitdiff/ce8ec963300dde513074a182635b23b46e2a9f3f

>---------------------------------------------------------------

commit ce8ec963300dde513074a182635b23b46e2a9f3f
Author: Herbert Valerio Riedel <hvr at gnu.org>
Date:   Sun Sep 29 18:25:07 2013 +0200

    Expose GMP's `mpz_gcdext()` as internal primitive
    
    The extended GCD computation is useful to have for implementing
    algorithms such as the chinese reminder theorem.
    
    Signed-off-by: Herbert Valerio Riedel <hvr at gnu.org>


>---------------------------------------------------------------

ce8ec963300dde513074a182635b23b46e2a9f3f
 GHC/Integer/GMP/Internals.hs |    2 +-
 GHC/Integer/GMP/Prim.hs      |    6 ++++++
 GHC/Integer/Type.lhs         |   13 ++++++++++++-
 cbits/gmp-wrappers.cmm       |    3 +++
 4 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/GHC/Integer/GMP/Internals.hs b/GHC/Integer/GMP/Internals.hs
index 4a7ff5d..b80840b 100644
--- a/GHC/Integer/GMP/Internals.hs
+++ b/GHC/Integer/GMP/Internals.hs
@@ -1,6 +1,6 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 
-module GHC.Integer.GMP.Internals (Integer(..), gcdInt, gcdInteger, lcmInteger, powInteger, powModInteger, recipModInteger)
+module GHC.Integer.GMP.Internals (Integer(..), gcdInt, gcdInteger, gcdExtInteger, lcmInteger, powInteger, powModInteger, recipModInteger)
     where
 
 import GHC.Integer.Type
diff --git a/GHC/Integer/GMP/Prim.hs b/GHC/Integer/GMP/Prim.hs
index 59aa6f4..de9477f 100644
--- a/GHC/Integer/GMP/Prim.hs
+++ b/GHC/Integer/GMP/Prim.hs
@@ -21,6 +21,7 @@ module GHC.Integer.GMP.Prim (
     divExactInteger#,
 
     gcdInteger#,
+    gcdExtInteger#,
     gcdIntegerInt#,
     gcdInt#,
 
@@ -124,6 +125,11 @@ foreign import prim "integer_cmm_divExactIntegerzh" divExactInteger#
 foreign import prim "integer_cmm_gcdIntegerzh" gcdInteger#
   :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray# #)
 
+-- | Extended greatest common divisor.
+--
+foreign import prim "integer_cmm_gcdExtIntegerzh" gcdExtInteger#
+  :: Int# -> ByteArray# -> Int# -> ByteArray# -> (# Int#, ByteArray#, Int#, ByteArray# #)
+
 -- | Greatest common divisor, where second argument is an ordinary {\tt Int\#}.
 --
 foreign import prim "integer_cmm_gcdIntegerIntzh" gcdIntegerInt#
diff --git a/GHC/Integer/Type.lhs b/GHC/Integer/Type.lhs
index 554160c..3d4994a 100644
--- a/GHC/Integer/Type.lhs
+++ b/GHC/Integer/Type.lhs
@@ -40,7 +40,7 @@ import GHC.Integer.GMP.Prim (
     plusInteger#, minusInteger#, timesInteger#,
     quotRemInteger#, quotInteger#, remInteger#,
     divModInteger#, divInteger#, modInteger#,
-    gcdInteger#, gcdIntegerInt#, gcdInt#, divExactInteger#,
+    gcdInteger#, gcdExtInteger#, gcdIntegerInt#, gcdInt#, divExactInteger#,
     decodeDouble#,
     int2Integer#, integer2Int#, word2Integer#, integer2Word#,
     andInteger#, orInteger#, xorInteger#, complementInteger#,
@@ -272,6 +272,17 @@ gcdInteger ia@(J# _ _) ib@(S# _) = gcdInteger ib ia
 gcdInteger (J# sa a) (J# sb b)
   = case gcdInteger# sa a sb b of (# sg, g #) -> J# sg g
 
+-- | For a and b, compute their greatest common divisor g and the
+-- coefficient s satisfying @a*s + b*t = g at .
+{-# NOINLINE gcdExtInteger #-}
+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)
+  = case gcdExtInteger# sa a sb b of
+      (# sg, g, ss, s #) -> (# J# sg g, J# ss s #)
+
 {-# NOINLINE lcmInteger #-}
 lcmInteger :: Integer -> Integer -> Integer
 lcmInteger a b =      if a `eqInteger` S# 0# then S# 0#
diff --git a/cbits/gmp-wrappers.cmm b/cbits/gmp-wrappers.cmm
index 5c7bb0b..68e6485 100644
--- a/cbits/gmp-wrappers.cmm
+++ b/cbits/gmp-wrappers.cmm
@@ -36,6 +36,7 @@ import "integer-gmp" __gmpz_mul_2exp;
 import "integer-gmp" __gmpz_tstbit;
 import "integer-gmp" __gmpz_fdiv_q_2exp;
 import "integer-gmp" __gmpz_gcd;
+import "integer-gmp" __gmpz_gcdext;
 import "integer-gmp" __gmpn_gcd_1;
 import "integer-gmp" __gmpn_cmp;
 import "integer-gmp" __gmpz_tdiv_q;
@@ -417,6 +418,8 @@ GMP_TAKE2_RET1(integer_cmm_plusIntegerzh,           __gmpz_add)
 GMP_TAKE2_RET1(integer_cmm_minusIntegerzh,          __gmpz_sub)
 GMP_TAKE2_RET1(integer_cmm_timesIntegerzh,          __gmpz_mul)
 GMP_TAKE2_RET1(integer_cmm_gcdIntegerzh,            __gmpz_gcd)
+#define CMM_GMPZ_GCDEXT(g,s,a,b) __gmpz_gcdext(g,s,NULL,a,b)
+GMP_TAKE2_RET2(integer_cmm_gcdExtIntegerzh,         CMM_GMPZ_GCDEXT)
 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)




More information about the ghc-commits mailing list