[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