summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2020-09-24 11:33:33 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-09-25 21:14:36 -0400
commit04bc50b3c8e40387a0d0f090ea23cd68923f1834 (patch)
tree56eac59646066c462ef8e3e3dfa92d3e4a0b2ad9
parent92daad241bf136a10346ecbf520d62921c82bf7d (diff)
downloadhaskell-04bc50b3c8e40387a0d0f090ea23cd68923f1834.tar.gz
Bignum: implement extended GCD (#18427)
-rw-r--r--libraries/ghc-bignum/cbits/gmp_wrappers.c49
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/Backend/Check.hs16
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/Backend/FFI.hs17
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/Backend/GMP.hs81
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/Backend/Native.hs20
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/BigNat.hs-boot1
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/Integer.hs47
-rw-r--r--libraries/ghc-bignum/src/GHC/Num/Integer.hs-boot30
-rw-r--r--libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs7
-rw-r--r--testsuite/tests/lib/integer/all.T3
-rw-r--r--testsuite/tests/lib/integer/gcdeInteger.hs114
-rw-r--r--testsuite/tests/lib/integer/gcdeInteger.stdout1056
-rw-r--r--testsuite/tests/lib/integer/integerGcdExt.hs4
13 files changed, 1415 insertions, 30 deletions
diff --git a/libraries/ghc-bignum/cbits/gmp_wrappers.c b/libraries/ghc-bignum/cbits/gmp_wrappers.c
index cbcf768391..56075fd1f7 100644
--- a/libraries/ghc-bignum/cbits/gmp_wrappers.c
+++ b/libraries/ghc-bignum/cbits/gmp_wrappers.c
@@ -280,30 +280,32 @@ integer_gmp_mpn_gcd(mp_limb_t r[],
/* wraps mpz_gcdext()
*
* Set g={g0,gn} to the greatest common divisor of x={x0,xn} and
- * y={y0,yn}, and in addition set s={s0,sn} to coefficient
- * satisfying x*s + y*t = g.
- *
- * The g0 array is zero-padded (so that gn is fixed).
+ * y={y0,yn}, and in addition set s={s0,sn} and t={t0,tn} to
+ * coefficients satisfying x*s + y*t = g.
*
* g0 must have space for exactly gn=min(xn,yn) limbs.
* s0 must have space for at least yn limbs.
+ * t0 must have space for at least xn limbs.
+ *
+ * Actual sizes are returned by pointers.
*
- * return value: signed 'sn' of s={s0,sn} where |sn| >= 1
*/
-mp_size_t
-integer_gmp_gcdext(mp_limb_t s0[], mp_limb_t g0[],
+void
+integer_gmp_gcdext(mp_limb_t s0[], int32_t * ssn,
+ mp_limb_t t0[], int32_t * stn,
+ mp_limb_t g0[], int32_t * gn,
const mp_limb_t x0[], const mp_size_t xn,
const mp_limb_t y0[], const mp_size_t yn)
{
- const mp_size_t gn0 = mp_size_minabs(xn, yn);
const mpz_t x = CONST_MPZ_INIT(x0, mp_limb_zero_p(x0,xn) ? 0 : xn);
const mpz_t y = CONST_MPZ_INIT(y0, mp_limb_zero_p(y0,yn) ? 0 : yn);
- mpz_t g, s;
+ mpz_t g, s, t;
mpz_init (g);
mpz_init (s);
+ mpz_init (t);
- mpz_gcdext (g, s, NULL, x, y);
+ mpz_gcdext (g, s, t, x, y);
// g must be positive (0 <= gn).
// According to the docs for mpz_gcdext(), we have:
@@ -311,28 +313,31 @@ integer_gmp_gcdext(mp_limb_t s0[], mp_limb_t g0[],
// --> g < min(|y|, |x|)
// --> gn <= min(yn, xn)
// <-> gn <= gn0
- const mp_size_t gn = g[0]._mp_size;
- assert(0 <= gn && gn <= gn0);
- memset(g0, 0, gn0*sizeof(mp_limb_t));
- memcpy(g0, g[0]._mp_d, gn*sizeof(mp_limb_t));
+ const mp_size_t gn0 = mp_size_minabs(xn, yn);
+ *gn = g[0]._mp_size;
+ assert(0 <= *gn && *gn <= gn0);
+ memcpy(g0, g[0]._mp_d, *gn * sizeof(mp_limb_t));
mpz_clear (g);
// According to the docs for mpz_gcdext(), we have:
// |s| < |y| / 2g
// --> |s| < |y| (note g > 0)
// --> sn <= yn
- const mp_size_t ssn = s[0]._mp_size;
- const mp_size_t sn = mp_size_abs(ssn);
+ *ssn = s[0]._mp_size;
+ const mp_size_t sn = mp_size_abs(*ssn);
assert(sn <= mp_size_abs(yn));
memcpy(s0, s[0]._mp_d, sn*sizeof(mp_limb_t));
mpz_clear (s);
- if (!sn) {
- s0[0] = 0;
- return 1;
- }
-
- return ssn;
+ // According to the docs for mpz_gcdext(), we have:
+ // |t| < |x| / 2g
+ // --> |t| < |x| (note g > 0)
+ // --> st <= xn
+ *stn = t[0]._mp_size;
+ const mp_size_t tn = mp_size_abs(*stn);
+ assert(tn <= mp_size_abs(xn));
+ memcpy(t0, t[0]._mp_d, tn*sizeof(mp_limb_t));
+ mpz_clear (t);
}
/* Truncating (i.e. rounded towards zero) integer division-quotient of MPN */
diff --git a/libraries/ghc-bignum/src/GHC/Num/Backend/Check.hs b/libraries/ghc-bignum/src/GHC/Num/Backend/Check.hs
index 73f8366ad0..a8ee366312 100644
--- a/libraries/ghc-bignum/src/GHC/Num/Backend/Check.hs
+++ b/libraries/ghc-bignum/src/GHC/Num/Backend/Check.hs
@@ -16,6 +16,7 @@ import GHC.Prim
import GHC.Types
import GHC.Num.WordArray
import GHC.Num.Primitives
+import {-# SOURCE #-} GHC.Num.Integer
import qualified GHC.Num.Backend.Native as Native
import qualified GHC.Num.Backend.Selected as Other
@@ -453,3 +454,18 @@ bignat_powmod_words b e m =
in case gr `eqWord#` nr of
1# -> gr
_ -> unexpectedValue_Word# (# #)
+
+integer_gcde
+ :: Integer
+ -> Integer
+ -> (# Integer, Integer, Integer #)
+integer_gcde a b =
+ let
+ !(# g0,x0,y0 #) = Other.integer_gcde a b
+ !(# g1,x1,y1 #) = Native.integer_gcde a b
+ in if isTrue# (integerEq# x0 x1
+ &&# integerEq# y0 y1
+ &&# integerEq# g0 g1)
+ then (# g0, x0, y0 #)
+ else case unexpectedValue of
+ !_ -> (# integerZero, integerZero, integerZero #)
diff --git a/libraries/ghc-bignum/src/GHC/Num/Backend/FFI.hs b/libraries/ghc-bignum/src/GHC/Num/Backend/FFI.hs
index a049cfe332..3fddd19098 100644
--- a/libraries/ghc-bignum/src/GHC/Num/Backend/FFI.hs
+++ b/libraries/ghc-bignum/src/GHC/Num/Backend/FFI.hs
@@ -19,6 +19,7 @@ import GHC.Prim
import GHC.Types
import GHC.Num.WordArray
import GHC.Num.Primitives
+import qualified GHC.Num.Backend.Native as Native
default ()
@@ -579,3 +580,19 @@ bignat_powmod_words = ghc_bignat_powmod_words
foreign import ccall unsafe ghc_bignat_powmod_words
:: Word# -> Word# -> Word# -> Word#
+
+-- | Return extended GCD of two non-zero integers.
+--
+-- I.e. integer_gcde a b returns (g,x,y) so that ax + by = g
+--
+-- Input: a and b are non zero.
+-- Output: g must be > 0
+--
+integer_gcde
+ :: Integer
+ -> Integer
+ -> (# Integer, Integer, Integer #)
+integer_gcde = Native.integer_gcde
+ -- for now we use Native's implementation. If some FFI backend user needs a
+ -- specific implementation, we'll need to determine a prototype to pass and
+ -- return BigNat signs and sizes via FFI.
diff --git a/libraries/ghc-bignum/src/GHC/Num/Backend/GMP.hs b/libraries/ghc-bignum/src/GHC/Num/Backend/GMP.hs
index a340db573e..10242dfdc7 100644
--- a/libraries/ghc-bignum/src/GHC/Num/Backend/GMP.hs
+++ b/libraries/ghc-bignum/src/GHC/Num/Backend/GMP.hs
@@ -8,6 +8,9 @@
{-# LANGUAGE UnliftedFFITypes #-}
{-# LANGUAGE NegativeLiterals #-}
{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE LambdaCase #-}
+
+{-# OPTIONS_GHC -Wno-name-shadowing #-}
-- | Backend based on the GNU GMP library.
--
@@ -22,6 +25,9 @@ import GHC.Num.WordArray
import GHC.Num.Primitives
import GHC.Prim
import GHC.Types
+import GHC.Magic (runRW#)
+import {-# SOURCE #-} GHC.Num.Integer
+import {-# SOURCE #-} GHC.Num.BigNat
default ()
@@ -352,6 +358,70 @@ bignat_powmod r b e m s =
case ioInt# (integer_gmp_powm# r b (wordArraySize# b) e (wordArraySize# e) m (wordArraySize# m)) s of
(# s', n #) -> mwaSetSize# r (narrowGmpSize# n) s'
+integer_gcde
+ :: Integer
+ -> Integer
+ -> (# Integer, Integer, Integer #)
+integer_gcde a b = case runRW# io of (# _, a #) -> a
+ where
+ !(# sa, ba #) = integerToBigNatSign# a
+ !(# sb, bb #) = integerToBigNatSign# b
+ !sza = bigNatSize# ba
+ !szb = bigNatSize# bb
+ -- signed sizes of a and b
+ !ssa = case sa of
+ 0# -> sza
+ _ -> negateInt# sza
+ !ssb = case sb of
+ 0# -> szb
+ _ -> negateInt# szb
+
+ -- gcd(a,b) < min(a,b)
+ !g_init_sz = minI# sza szb
+
+ -- According to https://gmplib.org/manual/Number-Theoretic-Functions.html#index-mpz_005fgcdext
+ -- a*x + b*y = g
+ -- abs(x) < abs(b) / (2 g) < abs(b)
+ -- abs(y) < abs(a) / (2 g) < abs(a)
+ !x_init_sz = szb
+ !y_init_sz = sza
+
+ io s =
+ -- allocate output arrays
+ case newWordArray# g_init_sz s of { (# s, mbg #) ->
+ case newWordArray# x_init_sz s of { (# s, mbx #) ->
+ case newWordArray# y_init_sz s of { (# s, mby #) ->
+ -- allocate space to return sizes (3x4 = 12)
+ case newPinnedByteArray# 12# s of { (# s, mszs #) ->
+ case unsafeFreezeByteArray# mszs s of { (# s, szs #) ->
+ let !ssx_ptr = byteArrayContents# szs in
+ let !ssy_ptr = ssx_ptr `plusAddr#` 4# in
+ let !sg_ptr = ssy_ptr `plusAddr#` 4# in
+ -- call GMP
+ case ioVoid (integer_gmp_gcdext# mbx ssx_ptr mby ssy_ptr mbg sg_ptr ba ssa bb ssb) s of { s ->
+ -- read sizes
+ case readInt32OffAddr# ssx_ptr 0# s of { (# s, ssx #) ->
+ case readInt32OffAddr# ssy_ptr 0# s of { (# s, ssy #) ->
+ case readInt32OffAddr# sg_ptr 0# s of { (# s, sg #) ->
+ case touch# szs s of { s ->
+ -- shrink x, y and g to their actual sizes and freeze them
+ let !sx = absI# ssx in
+ let !sy = absI# ssy in
+ case mwaSetSize# mbx sx s of { s ->
+ case mwaSetSize# mby sy s of { s ->
+ case mwaSetSize# mbg sg s of { s ->
+
+ -- return x, y and g as Integer
+ case unsafeFreezeByteArray# mbx s of { (# s, bx #) ->
+ case unsafeFreezeByteArray# mby s of { (# s, by #) ->
+ case unsafeFreezeByteArray# mbg s of { (# s, bg #) ->
+
+ (# s, (# integerFromBigNat# bg
+ , integerFromBigNatSign# (ssx <# 0#) bx
+ , integerFromBigNatSign# (ssy <# 0#) by #) #)
+ }}}}}}}}}}}}}}}}
+
+
----------------------------------------------------------------------
-- FFI ccall imports
@@ -366,10 +436,13 @@ foreign import ccall unsafe "integer_gmp_mpn_gcd"
c_mpn_gcd# :: MutableByteArray# s -> ByteArray# -> GmpSize#
-> ByteArray# -> GmpSize# -> IO GmpSize
-foreign import ccall unsafe "integer_gmp_gcdext"
- integer_gmp_gcdext# :: MutableByteArray# s -> MutableByteArray# s
- -> ByteArray# -> GmpSize#
- -> ByteArray# -> GmpSize# -> IO GmpSize
+foreign import ccall unsafe "integer_gmp_gcdext" integer_gmp_gcdext#
+ :: MutableByteArray# s -> Addr#
+ -> MutableByteArray# s -> Addr#
+ -> MutableByteArray# s -> Addr#
+ -> ByteArray# -> GmpSize#
+ -> ByteArray# -> GmpSize#
+ -> IO ()
-- mp_limb_t mpn_add_1 (mp_limb_t *rp, const mp_limb_t *s1p, mp_size_t n,
-- mp_limb_t s2limb)
diff --git a/libraries/ghc-bignum/src/GHC/Num/Backend/Native.hs b/libraries/ghc-bignum/src/GHC/Num/Backend/Native.hs
index 1169af41d6..db4196f51f 100644
--- a/libraries/ghc-bignum/src/GHC/Num/Backend/Native.hs
+++ b/libraries/ghc-bignum/src/GHC/Num/Backend/Native.hs
@@ -17,9 +17,11 @@ module GHC.Num.Backend.Native where
#if defined(BIGNUM_NATIVE) || defined(BIGNUM_CHECK)
import {-# SOURCE #-} GHC.Num.BigNat
import {-# SOURCE #-} GHC.Num.Natural
+import {-# SOURCE #-} GHC.Num.Integer
#else
import GHC.Num.BigNat
import GHC.Num.Natural
+import GHC.Num.Integer
#endif
import GHC.Num.WordArray
import GHC.Num.Primitives
@@ -717,3 +719,21 @@ bignat_powmod_words b e m =
bignat_powmod_word (wordArrayFromWord# b)
(wordArrayFromWord# e)
m
+
+
+integer_gcde
+ :: Integer
+ -> Integer
+ -> (# Integer, Integer, Integer #)
+integer_gcde a b = f (# a,integerOne,integerZero #) (# b,integerZero,integerOne #)
+ where
+ -- returned "g" must be positive
+ fix (# g, x, y #)
+ | integerIsNegative g = (# integerNegate g, integerNegate x, integerNegate y #)
+ | True = (# g,x,y #)
+
+ f old@(# old_g, old_s, old_t #) new@(# g, s, t #)
+ | integerIsZero g = fix old
+ | True = case integerQuotRem# old_g g of
+ !(# q, r #) -> f new (# r , old_s `integerSub` (q `integerMul` s)
+ , old_t `integerSub` (q `integerMul` t) #)
diff --git a/libraries/ghc-bignum/src/GHC/Num/BigNat.hs-boot b/libraries/ghc-bignum/src/GHC/Num/BigNat.hs-boot
index 90a3f11ea1..37edb97582 100644
--- a/libraries/ghc-bignum/src/GHC/Num/BigNat.hs-boot
+++ b/libraries/ghc-bignum/src/GHC/Num/BigNat.hs-boot
@@ -10,6 +10,7 @@ import GHC.Prim
type BigNat# = WordArray#
data BigNat = BN# { unBigNat :: BigNat# }
+bigNatSize# :: BigNat# -> Int#
bigNatSubUnsafe :: BigNat# -> BigNat# -> BigNat#
bigNatMulWord# :: BigNat# -> Word# -> BigNat#
bigNatRem :: BigNat# -> BigNat# -> BigNat#
diff --git a/libraries/ghc-bignum/src/GHC/Num/Integer.hs b/libraries/ghc-bignum/src/GHC/Num/Integer.hs
index 04dd57b291..43e4a18cdd 100644
--- a/libraries/ghc-bignum/src/GHC/Num/Integer.hs
+++ b/libraries/ghc-bignum/src/GHC/Num/Integer.hs
@@ -6,6 +6,7 @@
{-# LANGUAGE NegativeLiterals #-}
{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE BlockArguments #-}
+{-# LANGUAGE LambdaCase #-}
-- |
-- Module : GHC.Num.Integer
@@ -31,6 +32,7 @@ import GHC.Magic
import GHC.Num.Primitives
import GHC.Num.BigNat
import GHC.Num.Natural
+import qualified GHC.Num.Backend as Backend
#if WORD_SIZE_IN_BITS < 64
import GHC.IntWord64
@@ -113,6 +115,17 @@ integerFromBigNatSign# !sign !bn
| True
= integerFromBigNatNeg# bn
+-- | Convert an Integer into a sign-bit and a BigNat
+integerToBigNatSign# :: Integer -> (# Int#, BigNat# #)
+integerToBigNatSign# = \case
+ IS x
+ | isTrue# (x >=# 0#)
+ -> (# 0#, bigNatFromWord# (int2Word# x) #)
+ | True
+ -> (# 1#, bigNatFromWord# (int2Word# (negateInt# x)) #)
+ IP x -> (# 0#, x #)
+ IN x -> (# 1#, x #)
+
-- | Convert an Integer into a BigNat.
--
-- Return 0 for negative Integers.
@@ -853,7 +866,7 @@ integerDivMod# :: Integer -> Integer -> (# Integer, Integer #)
{-# NOINLINE integerDivMod# #-}
integerDivMod# !n !d
| isTrue# (integerSignum# r ==# negateInt# (integerSignum# d))
- = let !q' = integerAdd q (IS -1#) -- TODO: optimize
+ = let !q' = integerSub q (IS 1#)
!r' = integerAdd r d
in (# q', r' #)
| True = qr
@@ -1169,3 +1182,35 @@ integerFromByteArray# sz ba off e s = case bigNatFromByteArray# sz ba off e s of
integerFromByteArray :: Word# -> ByteArray# -> Word# -> Bool# -> Integer
integerFromByteArray sz ba off e = case runRW# (integerFromByteArray# sz ba off e) of
(# _, i #) -> i
+
+
+-- | Get the extended GCD of two integers.
+--
+-- `integerGcde# a b` returns (# g,x,y #) where
+-- * ax + by = g = |gcd a b|
+integerGcde#
+ :: Integer
+ -> Integer
+ -> (# Integer, Integer, Integer #)
+integerGcde# a b
+ | integerIsZero a && integerIsZero b = (# integerZero, integerZero, integerZero #)
+ | integerIsZero a = fix (# b , integerZero, integerOne #)
+ | integerIsZero b = fix (# a , integerOne, integerZero #)
+ | integerAbs a `integerEq` integerAbs b = fix (# b , integerZero, integerOne #)
+ | True = Backend.integer_gcde a b
+ where
+ -- returned "g" must be positive
+ fix (# g, x, y #)
+ | integerIsNegative g = (# integerNegate g, integerNegate x, integerNegate y #)
+ | True = (# g,x,y #)
+
+-- | Get the extended GCD of two integers.
+--
+-- `integerGcde a b` returns (g,x,y) where
+-- * ax + by = g = |gcd a b|
+integerGcde
+ :: Integer
+ -> Integer
+ -> ( Integer, Integer, Integer)
+integerGcde a b = case integerGcde# a b of
+ (# g,x,y #) -> (g,x,y)
diff --git a/libraries/ghc-bignum/src/GHC/Num/Integer.hs-boot b/libraries/ghc-bignum/src/GHC/Num/Integer.hs-boot
new file mode 100644
index 0000000000..a07b9b7548
--- /dev/null
+++ b/libraries/ghc-bignum/src/GHC/Num/Integer.hs-boot
@@ -0,0 +1,30 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE MagicHash #-}
+
+module GHC.Num.Integer where
+
+import GHC.Types
+import GHC.Prim
+import {-# SOURCE #-} GHC.Num.BigNat
+
+data Integer
+
+integerZero :: Integer
+integerOne :: Integer
+
+integerEq# :: Integer -> Integer -> Int#
+integerEq :: Integer -> Integer -> Bool
+integerGt :: Integer -> Integer -> Bool
+integerIsZero :: Integer -> Bool
+integerIsNegative :: Integer -> Bool
+
+integerSub :: Integer -> Integer -> Integer
+integerMul :: Integer -> Integer -> Integer
+integerNegate :: Integer -> Integer
+integerDivMod# :: Integer -> Integer -> (# Integer, Integer #)
+integerQuotRem# :: Integer -> Integer -> (# Integer, Integer #)
+
+integerToBigNatSign# :: Integer -> (# Int#, BigNat# #)
+integerFromBigNatSign# :: Int# -> BigNat# -> Integer
+integerFromBigNat# :: BigNat# -> Integer
diff --git a/libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs b/libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs
index e414846d96..3d5fabe6c0 100644
--- a/libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs
+++ b/libraries/integer-gmp/src/GHC/Integer/GMP/Internals.hs
@@ -29,6 +29,7 @@ module GHC.Integer.GMP.Internals
-- ** Additional 'Integer' operations
, gcdInteger
+ , gcdExtInteger
, lcmInteger
, sqrInteger
@@ -170,6 +171,12 @@ isValidInteger# = I.integerCheck#
gcdInteger :: Integer -> Integer -> Integer
gcdInteger = I.integerGcd
+{-# DEPRECATED gcdExtInteger "Use integerGcde instead" #-}
+gcdExtInteger :: Integer -> Integer -> (# Integer, Integer #)
+gcdExtInteger a b = case I.integerGcde# a b of
+ (# g, s, _t #) -> (# g, s #)
+
+
{-# DEPRECATED lcmInteger "Use integerLcm instead" #-}
lcmInteger :: Integer -> Integer -> Integer
lcmInteger = I.integerLcm
diff --git a/testsuite/tests/lib/integer/all.T b/testsuite/tests/lib/integer/all.T
index 0e32d11981..45270453a1 100644
--- a/testsuite/tests/lib/integer/all.T
+++ b/testsuite/tests/lib/integer/all.T
@@ -5,11 +5,12 @@ test('integerConstantFolding', normal, makefile_test, ['integerConstantFolding']
test('fromToInteger', [], makefile_test, ['fromToInteger'])
test('IntegerConversionRules', [], makefile_test, ['IntegerConversionRules'])
test('gcdInteger', normal, compile_and_run, [''])
+test('gcdeInteger', normal, compile_and_run, [''])
test('integerPowMod', [], compile_and_run, [''])
+test('integerGcdExt', [omit_ways(['ghci'])], compile_and_run, [''])
# skip ghci as it doesn't support unboxed tuples
test('integerImportExport', [omit_ways(['ghci'])], compile_and_run, [''])
# Disable GMP only tests
-#test('integerGcdExt', [omit_ways(['ghci'])], compile_and_run, [''])
#test('integerGmpInternals', [], compile_and_run, [''])
diff --git a/testsuite/tests/lib/integer/gcdeInteger.hs b/testsuite/tests/lib/integer/gcdeInteger.hs
new file mode 100644
index 0000000000..9fabc2cbce
--- /dev/null
+++ b/testsuite/tests/lib/integer/gcdeInteger.hs
@@ -0,0 +1,114 @@
+
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE MultiWayIf #-}
+
+module Main (main) where
+
+import GHC.Base
+import GHC.Num.Integer
+import Control.Monad
+import System.Exit
+
+main :: IO ()
+main = do
+
+ let test a b = do
+ putStrLn $ "GCDE " ++ show a ++ " " ++ show b
+ let r@(g,x,y) = integerGcde a b
+ putStrLn $ " -> g = " ++ show g
+ putStrLn $ " -> x = " ++ show x
+ putStrLn $ " -> y = " ++ show y
+ let sign a | a >= 0 = 1
+ | otherwise = -1
+ let assert text cond term
+ | not cond = return ()
+ | term = return ()
+ | otherwise = do
+ putStrLn $ "FAILED: " ++ text
+ putStrLn $ "a*x + b*y = g"
+ putStrLn $ "a = " ++ show a
+ putStrLn $ "b = " ++ show b
+ putStrLn $ "x = " ++ show x
+ putStrLn $ "y = " ++ show y
+ putStrLn $ "g = " ++ show g
+ putStrLn $ "expected g = " ++ show (abs (integerGcd a b))
+ exitFailure
+
+ -- check properties
+ assert "g >= 0" True (g >= 0)
+ assert "a*x + b*y = g" True (a*x + b*y == g)
+ assert "g = abs (gcd a b)" True (g == abs (integerGcd a b))
+
+ if -- special cases
+ | a == 0 && b == 0 -> do
+ assert "a == 0 && b ==0 ==> g == 0" (a == 0 && b == 0) (g == 0)
+
+ | abs a == abs b -> do
+ assert "abs a == abs b ==> x == 0 && y == sign b && g == abs a"
+ (abs a == abs b) (x == 0 && y == sign b && g == abs a)
+
+ -- non special cases
+ | otherwise -> do
+ assert "b == 0 ==> x=sign a"
+ (b == 0)
+ (x == sign a)
+
+ assert "abs b == 2g ==> x=sign a"
+ (abs b == 2*g)
+ (x == sign a)
+
+ assert "b /= 0 ==> abs x <= abs b / 2*g"
+ (b /= 0)
+ (abs x <= abs b `div` 2 * g)
+
+ assert "a /= 0 ==> abs y <= abs a / 2*g"
+ (a /= 0)
+ (abs y <= abs a `div` 2 * g)
+
+ assert "a == 0 ==> y=sign b"
+ (a == 0)
+ (y == sign b)
+
+ assert "abs a == 2g ==> y==sign b"
+ (abs a == 2*g)
+ (y == sign b)
+
+ assert "x == 0 ==> g == abs b"
+ (x == 0)
+ (g == abs b)
+
+ nums =
+ [ 0
+ , 1
+ , 7
+ , 14
+ , 123
+ , 1230
+ , 123456789456789456789456789456789456789465789465456789465454645789
+ , 4 * 123456789456789456789456789456789456789465789465456789465454645789
+ , -1
+ , -123
+ , -123456789456789456789456789456789456789465789465456789465454645789
+ , 4567897897897897899789897897978978979789
+ , 2988348162058574136915891421498819466320163312926952423791023078876139
+ , 2351399303373464486466122544523690094744975233415544072992656881240319
+ , 5328841272400314897981163497728751426
+ , 32052182750761975518649228050096851724
+ ]
+
+ forM_ nums $ \a ->
+ forM_ nums $ \b ->
+ test a b
+
+ -- see #15350
+ do
+ let a = 2
+ b = 2^65 + 1
+ test a b
+ test a (-b)
+ test (-a) b
+ test (-a) (-b)
+ test b a
+ test b (-a)
+ test (-b) a
+ test (-b) (-a)
diff --git a/testsuite/tests/lib/integer/gcdeInteger.stdout b/testsuite/tests/lib/integer/gcdeInteger.stdout
new file mode 100644
index 0000000000..f4854ddb08
--- /dev/null
+++ b/testsuite/tests/lib/integer/gcdeInteger.stdout
@@ -0,0 +1,1056 @@
+GCDE 0 0
+ -> g = 0
+ -> x = 0
+ -> y = 0
+GCDE 0 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 0 7
+ -> g = 7
+ -> x = 0
+ -> y = 1
+GCDE 0 14
+ -> g = 14
+ -> x = 0
+ -> y = 1
+GCDE 0 123
+ -> g = 123
+ -> x = 0
+ -> y = 1
+GCDE 0 1230
+ -> g = 1230
+ -> x = 0
+ -> y = 1
+GCDE 0 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = 0
+ -> y = 1
+GCDE 0 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 493827157827157827157827157827157827157863157861827157861818583156
+ -> x = 0
+ -> y = 1
+GCDE 0 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 0 -123
+ -> g = 123
+ -> x = 0
+ -> y = -1
+GCDE 0 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = 0
+ -> y = -1
+GCDE 0 4567897897897897899789897897978978979789
+ -> g = 4567897897897897899789897897978978979789
+ -> x = 0
+ -> y = 1
+GCDE 0 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> x = 0
+ -> y = 1
+GCDE 0 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> x = 0
+ -> y = 1
+GCDE 0 5328841272400314897981163497728751426
+ -> g = 5328841272400314897981163497728751426
+ -> x = 0
+ -> y = 1
+GCDE 0 32052182750761975518649228050096851724
+ -> g = 32052182750761975518649228050096851724
+ -> x = 0
+ -> y = 1
+GCDE 1 0
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 1 7
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 14
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 123
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 1230
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 1 -123
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 5328841272400314897981163497728751426
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 1 32052182750761975518649228050096851724
+ -> g = 1
+ -> x = 1
+ -> y = 0
+GCDE 7 0
+ -> g = 7
+ -> x = 1
+ -> y = 0
+GCDE 7 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 7 7
+ -> g = 7
+ -> x = 0
+ -> y = 1
+GCDE 7 14
+ -> g = 7
+ -> x = 1
+ -> y = 0
+GCDE 7 123
+ -> g = 1
+ -> x = -35
+ -> y = 2
+GCDE 7 1230
+ -> g = 1
+ -> x = -527
+ -> y = 3
+GCDE 7 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -52910052624338338624052909767195481481199624056624338342337705338
+ -> y = 3
+GCDE 7 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 1
+ -> x = 70546736832451118165403879689593975308266165408832451123116940451
+ -> y = -1
+GCDE 7 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 7 -123
+ -> g = 1
+ -> x = -35
+ -> y = -2
+GCDE 7 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -52910052624338338624052909767195481481199624056624338342337705338
+ -> y = -3
+GCDE 7 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = -1305113685113685114225685113708279708511
+ -> y = 2
+GCDE 7 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = 1280720640882246058678239180642351199851498562682979610196152748089774
+ -> y = -3
+GCDE 7 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = -671828372392418424704606441292482884212850066690155449426473394640091
+ -> y = 2
+GCDE 7 5328841272400314897981163497728751426
+ -> g = 1
+ -> x = 2283789116742992099134784356169464897
+ -> y = -3
+GCDE 7 32052182750761975518649228050096851724
+ -> g = 1
+ -> x = -13736649750326560936563954878612936453
+ -> y = 3
+GCDE 14 0
+ -> g = 14
+ -> x = 1
+ -> y = 0
+GCDE 14 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 14 7
+ -> g = 7
+ -> x = 0
+ -> y = 1
+GCDE 14 14
+ -> g = 14
+ -> x = 0
+ -> y = 1
+GCDE 14 123
+ -> g = 1
+ -> x = 44
+ -> y = -5
+GCDE 14 1230
+ -> g = 2
+ -> x = 88
+ -> y = -1
+GCDE 14 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -26455026312169169312026454883597740740599812028312169171168852669
+ -> y = 3
+GCDE 14 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 2
+ -> x = 70546736832451118165403879689593975308266165408832451123116940451
+ -> y = -2
+GCDE 14 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 14 -123
+ -> g = 1
+ -> x = 44
+ -> y = 5
+GCDE 14 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -26455026312169169312026454883597740740599812028312169171168852669
+ -> y = -3
+GCDE 14 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = 1631392106392106392782106392135349635639
+ -> y = -5
+GCDE 14 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = 640360320441123029339119590321175599925749281341489805098076374044887
+ -> y = -3
+GCDE 14 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = 839785465490523030880758051615603605266062583362694311783091743300114
+ -> y = -5
+GCDE 14 5328841272400314897981163497728751426
+ -> g = 2
+ -> x = -380631519457165349855797392694910816
+ -> y = 1
+GCDE 14 32052182750761975518649228050096851724
+ -> g = 2
+ -> x = 2289441625054426822760659146435489409
+ -> y = -1
+GCDE 123 0
+ -> g = 123
+ -> x = 1
+ -> y = 0
+GCDE 123 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 123 7
+ -> g = 1
+ -> x = 2
+ -> y = -35
+GCDE 123 14
+ -> g = 1
+ -> x = -5
+ -> y = 44
+GCDE 123 123
+ -> g = 123
+ -> x = 0
+ -> y = 1
+GCDE 123 1230
+ -> g = 123
+ -> x = 1
+ -> y = 0
+GCDE 123 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -49181973035631572216938070596607181973039216941523436453717704420
+ -> y = 49
+GCDE 123 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 1
+ -> x = -172638762492421029006394860053396638762505006406980225919172350209
+ -> y = 43
+GCDE 123 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 123 -123
+ -> g = 123
+ -> x = 0
+ -> y = -1
+GCDE 123 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -49181973035631572216938070596607181973039216941523436453717704420
+ -> y = -49
+GCDE 123 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = 854159769525623184513558143524524524676
+ -> y = -23
+GCDE 123 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = 1360548756709594729002357069950682033446578418893571835221929206642795
+ -> y = -56
+GCDE 123 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = -1108789915411877562723862663271333540611451736082126473443691862698687
+ -> y = 58
+GCDE 123 5328841272400314897981163497728751426
+ -> g = 3
+ -> x = 606534778972393565623872268034166829
+ -> y = -14
+GCDE 123 32052182750761975518649228050096851724
+ -> g = 3
+ -> x = 1042347406528844732313796034149491113
+ -> y = -4
+GCDE 1230 0
+ -> g = 1230
+ -> x = 1
+ -> y = 0
+GCDE 1230 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 1230 7
+ -> g = 1
+ -> x = 3
+ -> y = -527
+GCDE 1230 14
+ -> g = 2
+ -> x = -1
+ -> y = 88
+GCDE 1230 123
+ -> g = 123
+ -> x = 0
+ -> y = 1
+GCDE 1230 1230
+ -> g = 1230
+ -> x = 0
+ -> y = 1
+GCDE 1230 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -4918197303563157221693807059660718197303921694152343645371770442
+ -> y = 49
+GCDE 1230 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 2
+ -> x = 113620394849663142346069175337468020394857946077152102174711104905
+ -> y = -283
+GCDE 1230 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 1230 -123
+ -> g = 123
+ -> x = 0
+ -> y = -1
+GCDE 1230 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -4918197303563157221693807059660718197303921694152343645371770442
+ -> y = -49
+GCDE 1230 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = -1741743182206596841464603344839139139448
+ -> y = 469
+GCDE 1230 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = -1358119205358327595557710003754341529815423814574119028373318618773790
+ -> y = 559
+GCDE 1230 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = 594540799470851589667450497029973674362347396416450574553427878102227
+ -> y = -311
+GCDE 1230 5328841272400314897981163497728751426
+ -> g = 6
+ -> x = 298934998207822543057479903531125080
+ -> y = -69
+GCDE 1230 32052182750761975518649228050096851724
+ -> g = 6
+ -> x = -1928342702078362754780522663176558559
+ -> y = 74
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 0
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = 1
+ -> y = 0
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 7
+ -> g = 1
+ -> x = 3
+ -> y = -52910052624338338624052909767195481481199624056624338342337705338
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 14
+ -> g = 1
+ -> x = 3
+ -> y = -26455026312169169312026454883597740740599812028312169171168852669
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 123
+ -> g = 1
+ -> x = 49
+ -> y = -49181973035631572216938070596607181973039216941523436453717704420
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 1230
+ -> g = 1
+ -> x = 49
+ -> y = -4918197303563157221693807059660718197303921694152343645371770442
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = 0
+ -> y = 1
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = 1
+ -> y = 0
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 -123
+ -> g = 1
+ -> x = 49
+ -> y = 49181973035631572216938070596607181973039216941523436453717704420
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = 0
+ -> y = -1
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = -142355531505412253555567593395647545708
+ -> y = 3847449587076097018280777909186630028091235782450380442052224817
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = 501499981494162622976489092493961483514126808861435716131179868189595
+ -> y = -20718328076357217180814970215022985846592184263422313201087532586
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = 608000101055682152473830041965606704242079033852469328931798308452101
+ -> y = -31922158162609726789179865549911873484290325403318594248193251952
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 5328841272400314897981163497728751426
+ -> g = 1
+ -> x = -233831227202814412604649442847121617
+ -> y = 5417322661629453658993420651614628087475941267504880682551205239
+GCDE 123456789456789456789456789456789456789465789465456789465454645789 32052182750761975518649228050096851724
+ -> g = 1
+ -> x = 2649042575281623182157985423209129457
+ -> y = -10203432759063496909071922280945854833629276496909075027106202353
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 0
+ -> g = 493827157827157827157827157827157827157863157861827157861818583156
+ -> x = 1
+ -> y = 0
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 7
+ -> g = 1
+ -> x = -1
+ -> y = 70546736832451118165403879689593975308266165408832451123116940451
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 14
+ -> g = 2
+ -> x = -2
+ -> y = 70546736832451118165403879689593975308266165408832451123116940451
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 123
+ -> g = 1
+ -> x = 43
+ -> y = -172638762492421029006394860053396638762505006406980225919172350209
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 1230
+ -> g = 2
+ -> x = -283
+ -> y = 113620394849663142346069175337468020394857946077152102174711104905
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = 0
+ -> y = 1
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 493827157827157827157827157827157827157863157861827157861818583156
+ -> x = 0
+ -> y = 1
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 -123
+ -> g = 1
+ -> x = 43
+ -> y = 172638762492421029006394860053396638762505006406980225919172350209
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = 0
+ -> y = -1
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = -35588882876353063388891898348911886427
+ -> y = 3847449587076097018280777909186630028091235782450380442052224817
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = -621712045141102878484850582251214495701509126016379176914960802671636
+ -> y = 102738461380432239608641819241766470942873605202034476264367113203
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = 739849851107286659734988146622324199746763566817003350481113797423105
+ -> y = -155378947619399183578636655006701330273756114868775383713647897741
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 5328841272400314897981163497728751426
+ -> g = 2
+ -> x = 1215294704498671518192966153008627048
+ -> y = -112622144133530549471469948153560200614513906930447028100352235311
+GCDE 493827157827157827157827157827157827157863157861827157861818583156 32052182750761975518649228050096851724
+ -> g = 4
+ -> x = 2649042575281623182157985423209129457
+ -> y = -40813731036253987636287689123783419334517105987636300108424809412
+GCDE -1 0
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE -1 7
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 14
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 123
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 1230
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE -1 -123
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 5328841272400314897981163497728751426
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -1 32052182750761975518649228050096851724
+ -> g = 1
+ -> x = -1
+ -> y = 0
+GCDE -123 0
+ -> g = 123
+ -> x = -1
+ -> y = 0
+GCDE -123 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE -123 7
+ -> g = 1
+ -> x = -2
+ -> y = -35
+GCDE -123 14
+ -> g = 1
+ -> x = 5
+ -> y = 44
+GCDE -123 123
+ -> g = 123
+ -> x = 0
+ -> y = 1
+GCDE -123 1230
+ -> g = 123
+ -> x = -1
+ -> y = 0
+GCDE -123 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = 49181973035631572216938070596607181973039216941523436453717704420
+ -> y = 49
+GCDE -123 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 1
+ -> x = 172638762492421029006394860053396638762505006406980225919172350209
+ -> y = 43
+GCDE -123 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE -123 -123
+ -> g = 123
+ -> x = 0
+ -> y = -1
+GCDE -123 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = 49181973035631572216938070596607181973039216941523436453717704420
+ -> y = -49
+GCDE -123 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = -854159769525623184513558143524524524676
+ -> y = -23
+GCDE -123 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = -1360548756709594729002357069950682033446578418893571835221929206642795
+ -> y = -56
+GCDE -123 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = 1108789915411877562723862663271333540611451736082126473443691862698687
+ -> y = 58
+GCDE -123 5328841272400314897981163497728751426
+ -> g = 3
+ -> x = -606534778972393565623872268034166829
+ -> y = -14
+GCDE -123 32052182750761975518649228050096851724
+ -> g = 3
+ -> x = -1042347406528844732313796034149491113
+ -> y = -4
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 0
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = -1
+ -> y = 0
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 7
+ -> g = 1
+ -> x = -3
+ -> y = -52910052624338338624052909767195481481199624056624338342337705338
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 14
+ -> g = 1
+ -> x = -3
+ -> y = -26455026312169169312026454883597740740599812028312169171168852669
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 123
+ -> g = 1
+ -> x = -49
+ -> y = -49181973035631572216938070596607181973039216941523436453717704420
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 1230
+ -> g = 1
+ -> x = -49
+ -> y = -4918197303563157221693807059660718197303921694152343645371770442
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = 0
+ -> y = 1
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = -1
+ -> y = 0
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 -123
+ -> g = 1
+ -> x = -49
+ -> y = 49181973035631572216938070596607181973039216941523436453717704420
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 123456789456789456789456789456789456789465789465456789465454645789
+ -> x = 0
+ -> y = -1
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = 142355531505412253555567593395647545708
+ -> y = 3847449587076097018280777909186630028091235782450380442052224817
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = -501499981494162622976489092493961483514126808861435716131179868189595
+ -> y = -20718328076357217180814970215022985846592184263422313201087532586
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = -608000101055682152473830041965606704242079033852469328931798308452101
+ -> y = -31922158162609726789179865549911873484290325403318594248193251952
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 5328841272400314897981163497728751426
+ -> g = 1
+ -> x = 233831227202814412604649442847121617
+ -> y = 5417322661629453658993420651614628087475941267504880682551205239
+GCDE -123456789456789456789456789456789456789465789465456789465454645789 32052182750761975518649228050096851724
+ -> g = 1
+ -> x = -2649042575281623182157985423209129457
+ -> y = -10203432759063496909071922280945854833629276496909075027106202353
+GCDE 4567897897897897899789897897978978979789 0
+ -> g = 4567897897897897899789897897978978979789
+ -> x = 1
+ -> y = 0
+GCDE 4567897897897897899789897897978978979789 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 4567897897897897899789897897978978979789 7
+ -> g = 1
+ -> x = 2
+ -> y = -1305113685113685114225685113708279708511
+GCDE 4567897897897897899789897897978978979789 14
+ -> g = 1
+ -> x = -5
+ -> y = 1631392106392106392782106392135349635639
+GCDE 4567897897897897899789897897978978979789 123
+ -> g = 1
+ -> x = -23
+ -> y = 854159769525623184513558143524524524676
+GCDE 4567897897897897899789897897978978979789 1230
+ -> g = 1
+ -> x = 469
+ -> y = -1741743182206596841464603344839139139448
+GCDE 4567897897897897899789897897978978979789 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = 3847449587076097018280777909186630028091235782450380442052224817
+ -> y = -142355531505412253555567593395647545708
+GCDE 4567897897897897899789897897978978979789 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 1
+ -> x = 3847449587076097018280777909186630028091235782450380442052224817
+ -> y = -35588882876353063388891898348911886427
+GCDE 4567897897897897899789897897978978979789 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 4567897897897897899789897897978978979789 -123
+ -> g = 1
+ -> x = -23
+ -> y = -854159769525623184513558143524524524676
+GCDE 4567897897897897899789897897978978979789 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = 3847449587076097018280777909186630028091235782450380442052224817
+ -> y = 142355531505412253555567593395647545708
+GCDE 4567897897897897899789897897978978979789 4567897897897897899789897897978978979789
+ -> g = 4567897897897897899789897897978978979789
+ -> x = 0
+ -> y = 1
+GCDE 4567897897897897899789897897978978979789 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = -1015458101705415789288140664792006324531958465967800433101537202119645
+ -> y = 1552198297064637650702543759558133740654
+GCDE 4567897897897897899789897897978978979789 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = 683642522828502349233122722282318495240860998440822891959775694494728
+ -> y = -1328064203498637654577318574253233256089
+GCDE 4567897897897897899789897897978978979789 5328841272400314897981163497728751426
+ -> g = 1
+ -> x = 729028905639966888803280268153493563
+ -> y = -624925651816157654399317122483041604031
+GCDE 4567897897897897899789897897978978979789 32052182750761975518649228050096851724
+ -> g = 1
+ -> x = -12910967943414004413956938074429250463
+ -> y = 1839998972523827338782593728961148005767
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 0
+ -> g = 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> x = 1
+ -> y = 0
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 7
+ -> g = 1
+ -> x = -3
+ -> y = 1280720640882246058678239180642351199851498562682979610196152748089774
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 14
+ -> g = 1
+ -> x = -3
+ -> y = 640360320441123029339119590321175599925749281341489805098076374044887
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 123
+ -> g = 1
+ -> x = -56
+ -> y = 1360548756709594729002357069950682033446578418893571835221929206642795
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 1230
+ -> g = 1
+ -> x = 559
+ -> y = -1358119205358327595557710003754341529815423814574119028373318618773790
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -20718328076357217180814970215022985846592184263422313201087532586
+ -> y = 501499981494162622976489092493961483514126808861435716131179868189595
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 1
+ -> x = 102738461380432239608641819241766470942873605202034476264367113203
+ -> y = -621712045141102878484850582251214495701509126016379176914960802671636
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 -123
+ -> g = 1
+ -> x = -56
+ -> y = -1360548756709594729002357069950682033446578418893571835221929206642795
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -20718328076357217180814970215022985846592184263422313201087532586
+ -> y = -501499981494162622976489092493961483514126808861435716131179868189595
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = 1552198297064637650702543759558133740654
+ -> y = -1015458101705415789288140664792006324531958465967800433101537202119645
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> x = 0
+ -> y = 1
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = -238164827888328100873319793437342927637138278785737103723156342382925
+ -> y = 302679100340807588460107986194035692812415103244388831792688023418704
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 5328841272400314897981163497728751426
+ -> g = 1
+ -> x = 88969837841661133174308363831195241
+ -> y = -49893182739334638874406212208356173614356037934509167748717979955473
+GCDE 2988348162058574136915891421498819466320163312926952423791023078876139 32052182750761975518649228050096851724
+ -> g = 1
+ -> x = -2926808101621088968857550652617123241
+ -> y = 272877565911469778893036529750941765793334087149670477404511983087875
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 0
+ -> g = 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> x = 1
+ -> y = 0
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 7
+ -> g = 1
+ -> x = 2
+ -> y = -671828372392418424704606441292482884212850066690155449426473394640091
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 14
+ -> g = 1
+ -> x = -5
+ -> y = 839785465490523030880758051615603605266062583362694311783091743300114
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 123
+ -> g = 1
+ -> x = 58
+ -> y = -1108789915411877562723862663271333540611451736082126473443691862698687
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 1230
+ -> g = 1
+ -> x = -311
+ -> y = 594540799470851589667450497029973674362347396416450574553427878102227
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -31922158162609726789179865549911873484290325403318594248193251952
+ -> y = 608000101055682152473830041965606704242079033852469328931798308452101
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 1
+ -> x = -155378947619399183578636655006701330273756114868775383713647897741
+ -> y = 739849851107286659734988146622324199746763566817003350481113797423105
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 -123
+ -> g = 1
+ -> x = 58
+ -> y = 1108789915411877562723862663271333540611451736082126473443691862698687
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -31922158162609726789179865549911873484290325403318594248193251952
+ -> y = -608000101055682152473830041965606704242079033852469328931798308452101
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = -1328064203498637654577318574253233256089
+ -> y = 683642522828502349233122722282318495240860998440822891959775694494728
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = 302679100340807588460107986194035692812415103244388831792688023418704
+ -> y = -238164827888328100873319793437342927637138278785737103723156342382925
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> x = 0
+ -> y = 1
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 5328841272400314897981163497728751426
+ -> g = 1
+ -> x = 1320061761887019753142991170712833225
+ -> y = -582489165775607532361449347744188527071103823360367325716372563952699
+GCDE 2351399303373464486466122544523690094744975233415544072992656881240319 32052182750761975518649228050096851724
+ -> g = 1
+ -> x = -3459287250911140032199362006422486237
+ -> y = 253778836069059554551347740010931350716760250644753514181097821250371
+GCDE 5328841272400314897981163497728751426 0
+ -> g = 5328841272400314897981163497728751426
+ -> x = 1
+ -> y = 0
+GCDE 5328841272400314897981163497728751426 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 5328841272400314897981163497728751426 7
+ -> g = 1
+ -> x = -3
+ -> y = 2283789116742992099134784356169464897
+GCDE 5328841272400314897981163497728751426 14
+ -> g = 2
+ -> x = 1
+ -> y = -380631519457165349855797392694910816
+GCDE 5328841272400314897981163497728751426 123
+ -> g = 3
+ -> x = -14
+ -> y = 606534778972393565623872268034166829
+GCDE 5328841272400314897981163497728751426 1230
+ -> g = 6
+ -> x = -69
+ -> y = 298934998207822543057479903531125080
+GCDE 5328841272400314897981163497728751426 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = 5417322661629453658993420651614628087475941267504880682551205239
+ -> y = -233831227202814412604649442847121617
+GCDE 5328841272400314897981163497728751426 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 2
+ -> x = -112622144133530549471469948153560200614513906930447028100352235311
+ -> y = 1215294704498671518192966153008627048
+GCDE 5328841272400314897981163497728751426 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 5328841272400314897981163497728751426 -123
+ -> g = 3
+ -> x = -14
+ -> y = -606534778972393565623872268034166829
+GCDE 5328841272400314897981163497728751426 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = 5417322661629453658993420651614628087475941267504880682551205239
+ -> y = 233831227202814412604649442847121617
+GCDE 5328841272400314897981163497728751426 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = -624925651816157654399317122483041604031
+ -> y = 729028905639966888803280268153493563
+GCDE 5328841272400314897981163497728751426 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = -49893182739334638874406212208356173614356037934509167748717979955473
+ -> y = 88969837841661133174308363831195241
+GCDE 5328841272400314897981163497728751426 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = -582489165775607532361449347744188527071103823360367325716372563952699
+ -> y = 1320061761887019753142991170712833225
+GCDE 5328841272400314897981163497728751426 5328841272400314897981163497728751426
+ -> g = 5328841272400314897981163497728751426
+ -> x = 0
+ -> y = 1
+GCDE 5328841272400314897981163497728751426 32052182750761975518649228050096851724
+ -> g = 92889294
+ -> x = 115110207004456909698806038261
+ -> y = -19137667681784054624628973533
+GCDE 32052182750761975518649228050096851724 0
+ -> g = 32052182750761975518649228050096851724
+ -> x = 1
+ -> y = 0
+GCDE 32052182750761975518649228050096851724 1
+ -> g = 1
+ -> x = 0
+ -> y = 1
+GCDE 32052182750761975518649228050096851724 7
+ -> g = 1
+ -> x = 3
+ -> y = -13736649750326560936563954878612936453
+GCDE 32052182750761975518649228050096851724 14
+ -> g = 2
+ -> x = -1
+ -> y = 2289441625054426822760659146435489409
+GCDE 32052182750761975518649228050096851724 123
+ -> g = 3
+ -> x = -4
+ -> y = 1042347406528844732313796034149491113
+GCDE 32052182750761975518649228050096851724 1230
+ -> g = 6
+ -> x = 74
+ -> y = -1928342702078362754780522663176558559
+GCDE 32052182750761975518649228050096851724 123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -10203432759063496909071922280945854833629276496909075027106202353
+ -> y = 2649042575281623182157985423209129457
+GCDE 32052182750761975518649228050096851724 493827157827157827157827157827157827157863157861827157861818583156
+ -> g = 4
+ -> x = -40813731036253987636287689123783419334517105987636300108424809412
+ -> y = 2649042575281623182157985423209129457
+GCDE 32052182750761975518649228050096851724 -1
+ -> g = 1
+ -> x = 0
+ -> y = -1
+GCDE 32052182750761975518649228050096851724 -123
+ -> g = 3
+ -> x = -4
+ -> y = -1042347406528844732313796034149491113
+GCDE 32052182750761975518649228050096851724 -123456789456789456789456789456789456789465789465456789465454645789
+ -> g = 1
+ -> x = -10203432759063496909071922280945854833629276496909075027106202353
+ -> y = -2649042575281623182157985423209129457
+GCDE 32052182750761975518649228050096851724 4567897897897897899789897897978978979789
+ -> g = 1
+ -> x = 1839998972523827338782593728961148005767
+ -> y = -12910967943414004413956938074429250463
+GCDE 32052182750761975518649228050096851724 2988348162058574136915891421498819466320163312926952423791023078876139
+ -> g = 1
+ -> x = 272877565911469778893036529750941765793334087149670477404511983087875
+ -> y = -2926808101621088968857550652617123241
+GCDE 32052182750761975518649228050096851724 2351399303373464486466122544523690094744975233415544072992656881240319
+ -> g = 1
+ -> x = 253778836069059554551347740010931350716760250644753514181097821250371
+ -> y = -3459287250911140032199362006422486237
+GCDE 32052182750761975518649228050096851724 5328841272400314897981163497728751426
+ -> g = 92889294
+ -> x = -19137667681784054624628973533
+ -> y = 115110207004456909698806038261
+GCDE 32052182750761975518649228050096851724 32052182750761975518649228050096851724
+ -> g = 32052182750761975518649228050096851724
+ -> x = 0
+ -> y = 1
+GCDE 2 36893488147419103233
+ -> g = 1
+ -> x = -18446744073709551616
+ -> y = 1
+GCDE 2 -36893488147419103233
+ -> g = 1
+ -> x = -18446744073709551616
+ -> y = -1
+GCDE -2 36893488147419103233
+ -> g = 1
+ -> x = 18446744073709551616
+ -> y = 1
+GCDE -2 -36893488147419103233
+ -> g = 1
+ -> x = 18446744073709551616
+ -> y = -1
+GCDE 36893488147419103233 2
+ -> g = 1
+ -> x = 1
+ -> y = -18446744073709551616
+GCDE 36893488147419103233 -2
+ -> g = 1
+ -> x = 1
+ -> y = 18446744073709551616
+GCDE -36893488147419103233 2
+ -> g = 1
+ -> x = -1
+ -> y = -18446744073709551616
+GCDE -36893488147419103233 -2
+ -> g = 1
+ -> x = -1
+ -> y = 18446744073709551616
diff --git a/testsuite/tests/lib/integer/integerGcdExt.hs b/testsuite/tests/lib/integer/integerGcdExt.hs
index d060c2d3b2..2457b1ced2 100644
--- a/testsuite/tests/lib/integer/integerGcdExt.hs
+++ b/testsuite/tests/lib/integer/integerGcdExt.hs
@@ -9,10 +9,10 @@ import Control.Monad
import GHC.Word
import GHC.Base
-import qualified GHC.Integer.GMP.Internals as I
+import qualified GHC.Num.Integer as I
gcdExtInteger :: Integer -> Integer -> (Integer, Integer)
-gcdExtInteger a b = case I.gcdExtInteger a b of (# g, s #) -> (g, s)
+gcdExtInteger a b = case I.integerGcde a b of ( g, s, _t ) -> (g, s)
main :: IO ()
main = do