summaryrefslogtreecommitdiff
path: root/libraries
diff options
context:
space:
mode:
authorDavidEichamnn <EichmannD@gmail.com>2018-08-21 16:06:45 -0400
committerBen Gamari <ben@smart-cactus.org>2018-08-21 18:56:12 -0400
commitc331592130ef592b92084e7417581a4039bfa7d2 (patch)
tree485a050b23942a37ab1674564cf2fba996068bfe /libraries
parent2693eb11f55f2001701c90c24183e21c794a8be1 (diff)
downloadhaskell-c331592130ef592b92084e7417581a4039bfa7d2.tar.gz
Correct limb length and assertion for gcdExtInteger
Reviewers: hvr, bgamari, monoidal Reviewed By: monoidal Subscribers: monoidal, rwbarton, thomie, carter GHC Trac Issues: #15350 Differential Revision: https://phabricator.haskell.org/D5042
Diffstat (limited to 'libraries')
-rw-r--r--libraries/integer-gmp/cbits/wrappers.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/libraries/integer-gmp/cbits/wrappers.c b/libraries/integer-gmp/cbits/wrappers.c
index 8f147ad0c1..11e5179323 100644
--- a/libraries/integer-gmp/cbits/wrappers.c
+++ b/libraries/integer-gmp/cbits/wrappers.c
@@ -286,9 +286,9 @@ integer_gmp_mpn_gcd(mp_limb_t r[],
* reconstructed).
*
* g must have space for exactly gn=min(xn,yn) limbs.
- * s must have space for at least xn limbs.
+ * s must have space for at least yn limbs.
*
- * return value: signed 'sn' of {sp,sn}
+ * return value: signed 'sn' of {sp,sn} where |sn| >= 1
*/
mp_size_t
integer_gmp_gcdext(mp_limb_t s0[], mp_limb_t g0[],
@@ -305,15 +305,25 @@ integer_gmp_gcdext(mp_limb_t s0[], mp_limb_t g0[],
mpz_gcdext (g, s, NULL, x, y);
+ // g must be positive (0 <= gn).
+ // According to the docs for mpz_gcdext(), we have:
+ // g < min(|y|/2|s|, |x|/2|t|)
+ // --> 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));
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);
- assert(sn <= mp_size_abs(xn));
+ assert(sn <= mp_size_abs(yn));
memcpy(s0, s[0]._mp_d, sn*sizeof(mp_limb_t));
mpz_clear (s);