Skip to content

Commit 901f58c

Browse files
committed
Update mini-gmp
* src/mini-gmp.c, src/mini-gmp.h: Copy from GMP 6.2.0. This incorporates: 2019-12-05 remove some sizeof(mp_limb_t) 2019-12-04 (mpn_invert_3by2): Remove special code for limb sizes 2019-12-04 (mpn_invert_3by2): Limit size of an intermediate 2019-11-20 (mpn_invert_3by2): Use xor instead of negation 2019-11-19 (mpn_invert_3by2): Move an assert earlier 2019-11-19 (mpn_invert_3by2): Add a new shortcut 2019-11-17 Prepend "unsigned" to MINI_GMP_LIMB_TYPE 2019-11-17 Enable testing with different limb sizes (types) 2019-11-20 Use already defined constants 2019-11-09 Avoid undefined behaviour with small limb sizes
1 parent 491c909 commit 901f58c

File tree

2 files changed

+123
-107
lines changed

2 files changed

+123
-107
lines changed

src/mini-gmp.c

Lines changed: 117 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,13 @@ see https://www.gnu.org/licenses/. */
9494

9595
#define gmp_clz(count, x) do { \
9696
mp_limb_t __clz_x = (x); \
97-
unsigned __clz_c; \
98-
for (__clz_c = 0; \
99-
(__clz_x & ((mp_limb_t) 0xff << (GMP_LIMB_BITS - 8))) == 0; \
100-
__clz_c += 8) \
101-
__clz_x <<= 8; \
97+
unsigned __clz_c = 0; \
98+
int LOCAL_SHIFT_BITS = 8; \
99+
if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS) \
100+
for (; \
101+
(__clz_x & ((mp_limb_t) 0xff << (GMP_LIMB_BITS - 8))) == 0; \
102+
__clz_c += 8) \
103+
{ __clz_x <<= LOCAL_SHIFT_BITS; } \
102104
for (; (__clz_x & GMP_LIMB_HIGHBIT) == 0; __clz_c++) \
103105
__clz_x <<= 1; \
104106
(count) = __clz_c; \
@@ -143,27 +145,27 @@ see https://www.gnu.org/licenses/. */
143145
w1 = (mp_limb_t) (__ww >> LOCAL_GMP_LIMB_BITS); \
144146
} \
145147
else { \
146-
mp_limb_t __x0, __x1, __x2, __x3; \
147-
unsigned __ul, __vl, __uh, __vh; \
148-
mp_limb_t __u = (u), __v = (v); \
148+
mp_limb_t __x0, __x1, __x2, __x3; \
149+
unsigned __ul, __vl, __uh, __vh; \
150+
mp_limb_t __u = (u), __v = (v); \
149151
\
150-
__ul = __u & GMP_LLIMB_MASK; \
151-
__uh = __u >> (GMP_LIMB_BITS / 2); \
152-
__vl = __v & GMP_LLIMB_MASK; \
153-
__vh = __v >> (GMP_LIMB_BITS / 2); \
152+
__ul = __u & GMP_LLIMB_MASK; \
153+
__uh = __u >> (GMP_LIMB_BITS / 2); \
154+
__vl = __v & GMP_LLIMB_MASK; \
155+
__vh = __v >> (GMP_LIMB_BITS / 2); \
154156
\
155-
__x0 = (mp_limb_t) __ul * __vl; \
156-
__x1 = (mp_limb_t) __ul * __vh; \
157-
__x2 = (mp_limb_t) __uh * __vl; \
158-
__x3 = (mp_limb_t) __uh * __vh; \
157+
__x0 = (mp_limb_t) __ul * __vl; \
158+
__x1 = (mp_limb_t) __ul * __vh; \
159+
__x2 = (mp_limb_t) __uh * __vl; \
160+
__x3 = (mp_limb_t) __uh * __vh; \
159161
\
160-
__x1 += __x0 >> (GMP_LIMB_BITS / 2);/* this can't give carry */ \
161-
__x1 += __x2; /* but this indeed can */ \
162-
if (__x1 < __x2) /* did we get it? */ \
163-
__x3 += GMP_HLIMB_BIT; /* yes, add it in the proper pos. */ \
162+
__x1 += __x0 >> (GMP_LIMB_BITS / 2);/* this can't give carry */ \
163+
__x1 += __x2; /* but this indeed can */ \
164+
if (__x1 < __x2) /* did we get it? */ \
165+
__x3 += GMP_HLIMB_BIT; /* yes, add it in the proper pos. */ \
164166
\
165-
(w1) = __x3 + (__x1 >> (GMP_LIMB_BITS / 2)); \
166-
(w0) = (__x1 << (GMP_LIMB_BITS / 2)) + (__x0 & GMP_LLIMB_MASK); \
167+
(w1) = __x3 + (__x1 >> (GMP_LIMB_BITS / 2)); \
168+
(w0) = (__x1 << (GMP_LIMB_BITS / 2)) + (__x0 & GMP_LLIMB_MASK); \
167169
} \
168170
} while (0)
169171

@@ -768,91 +770,81 @@ mpn_neg (mp_ptr rp, mp_srcptr up, mp_size_t n)
768770
mp_limb_t
769771
mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0)
770772
{
771-
int GMP_LIMB_BITS_MUL_3 = GMP_LIMB_BITS * 3;
772-
if (sizeof (unsigned) * CHAR_BIT > GMP_LIMB_BITS * 3)
773-
{
774-
return (((unsigned) 1 << GMP_LIMB_BITS_MUL_3) - 1) /
775-
(((unsigned) u1 << GMP_LIMB_BITS_MUL_3 / 3) + u0);
776-
}
777-
else if (GMP_ULONG_BITS > GMP_LIMB_BITS * 3)
778-
{
779-
return (((unsigned long) 1 << GMP_LIMB_BITS_MUL_3) - 1) /
780-
(((unsigned long) u1 << GMP_LIMB_BITS_MUL_3 / 3) + u0);
781-
}
782-
else {
783-
mp_limb_t r, p, m, ql;
784-
unsigned ul, uh, qh;
773+
mp_limb_t r, m;
785774

786-
assert (u1 >= GMP_LIMB_HIGHBIT);
775+
{
776+
mp_limb_t p, ql;
777+
unsigned ul, uh, qh;
787778

788-
/* For notation, let b denote the half-limb base, so that B = b^2.
789-
Split u1 = b uh + ul. */
790-
ul = u1 & GMP_LLIMB_MASK;
791-
uh = u1 >> (GMP_LIMB_BITS / 2);
779+
/* For notation, let b denote the half-limb base, so that B = b^2.
780+
Split u1 = b uh + ul. */
781+
ul = u1 & GMP_LLIMB_MASK;
782+
uh = u1 >> (GMP_LIMB_BITS / 2);
792783

793-
/* Approximation of the high half of quotient. Differs from the 2/1
794-
inverse of the half limb uh, since we have already subtracted
795-
u0. */
796-
qh = ~u1 / uh;
784+
/* Approximation of the high half of quotient. Differs from the 2/1
785+
inverse of the half limb uh, since we have already subtracted
786+
u0. */
787+
qh = (u1 ^ GMP_LIMB_MAX) / uh;
797788

798-
/* Adjust to get a half-limb 3/2 inverse, i.e., we want
789+
/* Adjust to get a half-limb 3/2 inverse, i.e., we want
799790
800-
qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u
801-
= floor( (b (~u) + b-1) / u),
791+
qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u
792+
= floor( (b (~u) + b-1) / u),
802793
803-
and the remainder
794+
and the remainder
804795
805-
r = b (~u) + b-1 - qh (b uh + ul)
796+
r = b (~u) + b-1 - qh (b uh + ul)
806797
= b (~u - qh uh) + b-1 - qh ul
807798
808-
Subtraction of qh ul may underflow, which implies adjustments.
809-
But by normalization, 2 u >= B > qh ul, so we need to adjust by
810-
at most 2.
811-
*/
799+
Subtraction of qh ul may underflow, which implies adjustments.
800+
But by normalization, 2 u >= B > qh ul, so we need to adjust by
801+
at most 2.
802+
*/
812803

813-
r = ((~u1 - (mp_limb_t) qh * uh) << (GMP_LIMB_BITS / 2)) | GMP_LLIMB_MASK;
804+
r = ((~u1 - (mp_limb_t) qh * uh) << (GMP_LIMB_BITS / 2)) | GMP_LLIMB_MASK;
814805

815-
p = (mp_limb_t) qh * ul;
816-
/* Adjustment steps taken from udiv_qrnnd_c */
817-
if (r < p)
818-
{
819-
qh--;
820-
r += u1;
821-
if (r >= u1) /* i.e. we didn't get carry when adding to r */
822-
if (r < p)
823-
{
824-
qh--;
825-
r += u1;
826-
}
827-
}
828-
r -= p;
806+
p = (mp_limb_t) qh * ul;
807+
/* Adjustment steps taken from udiv_qrnnd_c */
808+
if (r < p)
809+
{
810+
qh--;
811+
r += u1;
812+
if (r >= u1) /* i.e. we didn't get carry when adding to r */
813+
if (r < p)
814+
{
815+
qh--;
816+
r += u1;
817+
}
818+
}
819+
r -= p;
829820

830-
/* Low half of the quotient is
821+
/* Low half of the quotient is
831822
832823
ql = floor ( (b r + b-1) / u1).
833824
834-
This is a 3/2 division (on half-limbs), for which qh is a
835-
suitable inverse. */
825+
This is a 3/2 division (on half-limbs), for which qh is a
826+
suitable inverse. */
836827

837-
p = (r >> (GMP_LIMB_BITS / 2)) * qh + r;
838-
/* Unlike full-limb 3/2, we can add 1 without overflow. For this to
839-
work, it is essential that ql is a full mp_limb_t. */
840-
ql = (p >> (GMP_LIMB_BITS / 2)) + 1;
828+
p = (r >> (GMP_LIMB_BITS / 2)) * qh + r;
829+
/* Unlike full-limb 3/2, we can add 1 without overflow. For this to
830+
work, it is essential that ql is a full mp_limb_t. */
831+
ql = (p >> (GMP_LIMB_BITS / 2)) + 1;
841832

842-
/* By the 3/2 trick, we don't need the high half limb. */
843-
r = (r << (GMP_LIMB_BITS / 2)) + GMP_LLIMB_MASK - ql * u1;
833+
/* By the 3/2 trick, we don't need the high half limb. */
834+
r = (r << (GMP_LIMB_BITS / 2)) + GMP_LLIMB_MASK - ql * u1;
844835

845-
if (r >= (p << (GMP_LIMB_BITS / 2)))
846-
{
847-
ql--;
848-
r += u1;
849-
}
850-
m = ((mp_limb_t) qh << (GMP_LIMB_BITS / 2)) + ql;
851-
if (r >= u1)
852-
{
853-
m++;
854-
r -= u1;
855-
}
836+
if (r >= (GMP_LIMB_MAX & (p << (GMP_LIMB_BITS / 2))))
837+
{
838+
ql--;
839+
r += u1;
840+
}
841+
m = ((mp_limb_t) qh << (GMP_LIMB_BITS / 2)) + ql;
842+
if (r >= u1)
843+
{
844+
m++;
845+
r -= u1;
846+
}
847+
}
856848

857849
/* Now m is the 2/1 inverse of u1. If u0 > 0, adjust it to become a
858850
3/2 inverse. */
@@ -881,7 +873,6 @@ mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0)
881873
}
882874

883875
return m;
884-
}
885876
}
886877

887878
struct gmp_div_inverse
@@ -3332,7 +3323,7 @@ mpz_bin_uiui (mpz_t r, unsigned long n, unsigned long k)
33323323
mpz_fac_ui (t, k);
33333324

33343325
for (; k > 0; --k)
3335-
mpz_mul_ui (r, r, n--);
3326+
mpz_mul_ui (r, r, n--);
33363327

33373328
mpz_divexact (r, r, t);
33383329
mpz_clear (t);
@@ -3427,7 +3418,7 @@ gmp_lucas_mod (mpz_t V, mpz_t Qk, long Q,
34273418
gmp_lucas_step_k_2k (V, Qk, n);
34283419

34293420
/* A step k->k+1 is performed if the bit in $n$ is 1 */
3430-
/* mpz_tstbit(n,bs) or the bit is 0 in $n$ but */
3421+
/* mpz_tstbit(n,bs) or the the bit is 0 in $n$ but */
34313422
/* should be 1 in $n+1$ (bs == b0) */
34323423
if (b0 == bs || mpz_tstbit (n, bs))
34333424
{
@@ -3990,13 +3981,18 @@ gmp_popcount_limb (mp_limb_t x)
39903981
unsigned c;
39913982

39923983
/* Do 16 bits at a time, to avoid limb-sized constants. */
3993-
for (c = 0; x > 0; x >>= 16)
3984+
int LOCAL_SHIFT_BITS = 16;
3985+
for (c = 0; x > 0;)
39943986
{
39953987
unsigned w = x - ((x >> 1) & 0x5555);
39963988
w = ((w >> 2) & 0x3333) + (w & 0x3333);
39973989
w = (w >> 4) + w;
39983990
w = ((w >> 8) & 0x000f) + (w & 0x000f);
39993991
c += w;
3992+
if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS)
3993+
x >>= LOCAL_SHIFT_BITS;
3994+
else
3995+
x = 0;
40003996
}
40013997
return c;
40023998
}
@@ -4492,7 +4488,7 @@ mpz_export (void *r, size_t *countp, int order, size_t size, int endian,
44924488
ptrdiff_t word_step;
44934489
/* The current (partial) limb. */
44944490
mp_limb_t limb;
4495-
/* The number of bytes left to do in this limb. */
4491+
/* The number of bytes left to to in this limb. */
44964492
size_t bytes;
44974493
/* The index where the limb was read. */
44984494
mp_size_t i;
@@ -4503,10 +4499,15 @@ mpz_export (void *r, size_t *countp, int order, size_t size, int endian,
45034499
limb = u->_mp_d[un-1];
45044500
assert (limb != 0);
45054501

4506-
k = 0;
4507-
do {
4508-
k++; limb >>= CHAR_BIT;
4509-
} while (limb != 0);
4502+
k = (GMP_LIMB_BITS <= CHAR_BIT);
4503+
if (!k)
4504+
{
4505+
do {
4506+
int LOCAL_CHAR_BIT = CHAR_BIT;
4507+
k++; limb >>= LOCAL_CHAR_BIT;
4508+
} while (limb != 0);
4509+
}
4510+
/* else limb = 0; */
45104511

45114512
count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size;
45124513

@@ -4535,17 +4536,28 @@ mpz_export (void *r, size_t *countp, int order, size_t size, int endian,
45354536
for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step)
45364537
{
45374538
size_t j;
4538-
for (j = 0; j < size; j++, p -= (ptrdiff_t) endian)
4539+
for (j = 0; j < size; ++j, p -= (ptrdiff_t) endian)
45394540
{
4540-
if (bytes == 0)
4541+
if (sizeof (mp_limb_t) == 1)
45414542
{
45424543
if (i < un)
4543-
limb = u->_mp_d[i++];
4544-
bytes = sizeof (mp_limb_t);
4544+
*p = u->_mp_d[i++];
4545+
else
4546+
*p = 0;
4547+
}
4548+
else
4549+
{
4550+
int LOCAL_CHAR_BIT = CHAR_BIT;
4551+
if (bytes == 0)
4552+
{
4553+
if (i < un)
4554+
limb = u->_mp_d[i++];
4555+
bytes = sizeof (mp_limb_t);
4556+
}
4557+
*p = limb;
4558+
limb >>= LOCAL_CHAR_BIT;
4559+
bytes--;
45454560
}
4546-
*p = limb;
4547-
limb >>= CHAR_BIT;
4548-
bytes--;
45494561
}
45504562
}
45514563
assert (i == un);

src/mini-gmp.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* mini-gmp, a minimalistic implementation of a GNU GMP subset.
22
3-
Copyright 2011-2015, 2017 Free Software Foundation, Inc.
3+
Copyright 2011-2015, 2017, 2019 Free Software Foundation, Inc.
44
55
This file is part of the GNU MP Library.
66
@@ -53,7 +53,11 @@ void mp_get_memory_functions (void *(**) (size_t),
5353
void *(**) (void *, size_t, size_t),
5454
void (**) (void *, size_t));
5555

56-
typedef unsigned long mp_limb_t;
56+
#ifndef MINI_GMP_LIMB_TYPE
57+
#define MINI_GMP_LIMB_TYPE long
58+
#endif
59+
60+
typedef unsigned MINI_GMP_LIMB_TYPE mp_limb_t;
5761
typedef long mp_size_t;
5862
typedef unsigned long mp_bitcnt_t;
5963

0 commit comments

Comments
 (0)