- Update from version 4.1.0 to 4.1.0 plus patches 1 to 13
- Version 4.1.0 was released on 10-07-2020. However patches have been progressively
issued to fix various bugs that have been identified.
- Currently 13 patches have been issued and mpfr provide a cumulative patches file to
use to patch the source file.
- Update of rootfile
- Patch changelog
1 With GCC (the only tested compiler with software _Decimal128), conversions of
double to _Decimal128 yield an increase of 2 to 3 MB for the generated library
code when the decimal encoding is BID (designed for software implementations),
even though the conversions done in MPFR are very simple. Details about this GCC
issue. The decimal128-conv patch avoids these conversions by directly using
_Decimal128 constants. Note that fixing the issue entirely would require to get
rid of all the decimal128 operations; in the mean time, decimal support (i.e.
mpfr_get_decimal128 and mpfr_set_decimal128 functions) could be disabled at
configure time.
Corresponding changeset in the 4.1 branch: 14094.
2 The random_deviate.c file contains non-portable code. This is fixed by the
random_deviate patch.
Corresponding changeset in the 4.1 branch: 14126.
3 In the mpfr_set_z_2exp function, a huge mpz_t value can yield an integer overflow.
This is fixed by the set_z_2exp-overflow patch (with testcases). Note that in
practice, an integer overflow may occur only with a 32-bit ABI. Moreover, with a
usual compilation, an integer overflow should here not yield any particular issue,
assuming that the processor does signed addition and multiplication modulo 2^32 (as
usual). However, UBsan would detect the overflow, and LTO might have unpredictable
effects.
Corresponding changesets in the 4.1 branch: 14147, 14151.
4 Some function prototypes are slightly inconsistent. This is valid C code, but
these inconsistencies are unintended and possibly confusing, and they trigger
diagnostics with the -Warray-parameter option of the future GCC 11 (included in
-Wall). This causes issues when testing MPFR. And since mpfr.h is concerned, this
might also affect user code. This is fixed by the prototypes patch.
Corresponding changeset in the 4.1 branch: 14411.
5 In uncommon cases, the mpfr_digamma function needs to use an intermediate
precision equal to the exponent of the input value, which may be huge. This is
inefficient, and the code can request more memory than available, yielding a crash.
The digamma-hugemem patch improves the implementation by making such a need much
rarer; it also provides testcases showing a crash on 64-bit machines (at least).
Corresponding changeset in the 4.1 branch: 14424.
6 The mpfr_digamma function may have an erratic behavior in some cases (an assertion
failure in debug mode). This is fixed by the digamma-interm-zero patch (with
testcase).
Corresponding changeset in the 4.1 branch: 14425.
7 The Bessel functions (mpfr_j0, mpfr_j1, mpfr_jn, mpfr_y0, mpfr_y1, mpfr_yn) may
have an erratic behavior in some cases (an assertion failure in debug mode). This
is fixed by the jn-interm-zero patch (with testcase).
Corresponding changeset in the 4.1 branch: 14426.
8 The mpfr_digamma function may have an erratic behavior in some cases (an assertion
failure in debug mode) when the reflection formula is used, i.e. when x < 1/2.
This is fixed by the digamma-interm-zero2 patch (with testcase).
Corresponding changeset in the 4.1 branch: 14435.
9 The Bessel functions (mpfr_j0, mpfr_j1, mpfr_jn, mpfr_y0, mpfr_y1, mpfr_yn) may
have an erratic behavior in some cases (an assertion failure in debug mode) when
the asymptotic expansion is needed. This is fixed by the jyn_asympt-interm-zero
patch (with testcase).
Corresponding changeset in the 4.1 branch: 14436.
10 Some functions are also implemented as macros, and such a macro should behave
exactly like the corresponding function (if the code is valid for the function
call). However, the following macros do not behave as if their argument were
implicitly converted to the type from the function prototype: mpfr_nan_p,
mpfr_inf_p, mpfr_zero_p, mpfr_regular_p, mpfr_get_prec, mpfr_get_exp,
mpfr_copysign (third argument), mpfr_signbit and mpfr_set (second argument). For
instance, providing an argument of type void * instead of mpfr_ptr or mpfr_srcptr
will yield a compilation failure. Note that this issue does not exist in C++,
which does not support such implicit conversions. Moreover, the mpfr_set macro
evaluates its second argument twice (reported by David McCooey), which is
incorrect if this evaluation has side effects. This is fixed by the macros patch
(with testcases). Macros for the custom interface, which are explicitly documented
as provided, do not follow these rules; the patch clarifies this point in the MPFR
manual.
Corresponding changesets in the 4.1 branch: 14468, 14469.
11 The test programs tset_si and tset_sj fail if MPFR_USE_NO_MACRO is defined (e.g.,
via -DMPFR_USE_NO_MACRO in CFLAGS). This is fixed by the tset_sij patch.
Corresponding changeset in the 4.1 branch: 14470.
12 The mpfr_get_str_ndigits function may raise the inexact flag. In a very reduced
exponent range (e.g. in which the result would not be representable as a MPFR
number), it has undefined behavior: it may return an incorrect value, crash, or
loop, taking more and more memory. This is fixed by the get_str_ndigits patch,
which also updates the tests to check these issues.
Corresponding changeset in the 4.1 branch: 14490.
13 The code for the formatted output functions (mpfr_printf, etc.) contains an
incorrect assertion, checked only in debug mode, i.e. when MPFR has been
configured with --enable-assert; this assertion failure occurs when the integer 0
(of either a native type or mpfr_prec_t with the length specifier P) is output
with the precision field equal to 0, i.e. when the corresponding string to output
is empty. Otherwise, there should be no side effects since the code is actually
valid in this case; but since the code incorrectly instructs the compiler that
some variable cannot be 0, there might be an issue with some optimizations (very
unlikely, though). This bug is fixed by the vasprintf-prec-zero patch, which also
provides testcases.
Corresponding changesets in the 4.1 branch: 14524, 14525.
Signed-off-by: Adolf Belka <adolf.belka(a)ipfire.org>
---
lfs/mpfr | 1 +
...pfr-4.1.0-cumulative-patches-1-to-13.patch | 2976 +++++++++++++++++
2 files changed, 2977 insertions(+)
create mode 100644 src/patches/mpfr-4.1.0-cumulative-patches-1-to-13.patch
diff --git a/lfs/mpfr b/lfs/mpfr
index b1c04afeb..221c9c527 100644
--- a/lfs/mpfr
+++ b/lfs/mpfr
@@ -70,6 +70,7 @@ $(subst %,%_BLAKE2,$(objects)) :
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
+ cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/mpfr-4.1.0-cumulative-patches-1-to-13.patch
cd $(DIR_APP) && $(CONFIGURE_ARGS) ./configure --prefix=/usr \
--enable-thread-safe
cd $(DIR_APP) && make $(MAKETUNING)
diff --git a/src/patches/mpfr-4.1.0-cumulative-patches-1-to-13.patch b/src/patches/mpfr-4.1.0-cumulative-patches-1-to-13.patch
new file mode 100644
index 000000000..3ecb16f1b
--- /dev/null
+++ b/src/patches/mpfr-4.1.0-cumulative-patches-1-to-13.patch
@@ -0,0 +1,2976 @@
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-02-11 12:40:40.079363480 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-02-11 12:40:40.119363040 +0000
+@@ -0,0 +1 @@
++decimal128-conv
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2020-07-10 11:52:33.000000000 +0000
++++ mpfr-4.1.0-b/VERSION 2021-02-11 12:40:40.119363040 +0000
+@@ -1 +1 @@
+-4.1.0
++4.1.0-p1
+diff -Naurd mpfr-4.1.0-a/src/get_d128.c mpfr-4.1.0-b/src/get_d128.c
+--- mpfr-4.1.0-a/src/get_d128.c 2020-04-08 22:39:35.000000000 +0000
++++ mpfr-4.1.0-b/src/get_d128.c 2021-02-11 12:40:40.103363216 +0000
+@@ -40,22 +40,21 @@
+ static _Decimal128
+ get_decimal128_nan (void)
+ {
+- return (_Decimal128) MPFR_DBL_NAN;
++ return 0.0dl / 0.0dl;
+ }
+
+ /* construct the decimal128 Inf with given sign */
+ static _Decimal128
+ get_decimal128_inf (int negative)
+ {
+- return (_Decimal128) (negative ? MPFR_DBL_INFM : MPFR_DBL_INFP);
++ return negative ? - 1.0dl / 0.0dl : 1.0dl / 0.0dl;
+ }
+
+ /* construct the decimal128 zero with given sign */
+ static _Decimal128
+ get_decimal128_zero (int negative)
+ {
+- _Decimal128 zero = 0;
+- return (_Decimal128) (negative ? -zero : zero);
++ return negative ? - 0.0dl : 0.0dl;
+ }
+
+ /* construct the decimal128 smallest non-zero with given sign:
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2020-07-10 11:52:33.000000000 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-02-11 12:40:40.115363084 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0"
++#define MPFR_VERSION_STRING "4.1.0-p1"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2020-07-10 11:52:33.000000000 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-02-11 12:40:40.119363040 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0";
++ return "4.1.0-p1";
+ }
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-02-11 12:43:51.761257868 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-02-11 12:43:51.801257430 +0000
+@@ -0,0 +1 @@
++random_deviate
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-02-11 12:40:40.119363040 +0000
++++ mpfr-4.1.0-b/VERSION 2021-02-11 12:43:51.801257430 +0000
+@@ -1 +1 @@
+-4.1.0-p1
++4.1.0-p2
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-02-11 12:40:40.115363084 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-02-11 12:43:51.801257430 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p1"
++#define MPFR_VERSION_STRING "4.1.0-p2"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+diff -Naurd mpfr-4.1.0-a/src/random_deviate.c mpfr-4.1.0-b/src/random_deviate.c
+--- mpfr-4.1.0-a/src/random_deviate.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/random_deviate.c 2021-02-11 12:43:51.789257562 +0000
+@@ -289,6 +289,7 @@
+ mpfr_random_size_t p = mpfr_get_prec (z); /* Number of bits in result */
+ mpz_t t;
+ int inex;
++ mpfr_exp_t negxe;
+
+ if (n == 0)
+ {
+@@ -370,14 +371,22 @@
+ mpz_setbit (t, 0); /* Set the trailing bit so result is always inexact */
+ if (neg)
+ mpz_neg (t, t);
+- /* Is -x->e representable as a mpfr_exp_t? */
+- MPFR_ASSERTN (x->e <= (mpfr_uexp_t)(-1) >> 1);
++ /* Portable version of the negation of x->e, with a check of overflow. */
++ if (MPFR_UNLIKELY (x->e > MPFR_EXP_MAX))
++ {
++ /* Overflow, except when x->e = MPFR_EXP_MAX + 1 = - MPFR_EXP_MIN. */
++ MPFR_ASSERTN (MPFR_EXP_MIN + MPFR_EXP_MAX == -1 &&
++ x->e == (mpfr_random_size_t) MPFR_EXP_MAX + 1);
++ negxe = MPFR_EXP_MIN;
++ }
++ else
++ negxe = - (mpfr_exp_t) x->e;
+ /*
+ * Let mpfr_set_z_2exp do all the work of rounding to the requested
+ * precision, setting overflow/underflow flags, and returning the right
+ * inexact value.
+ */
+- inex = mpfr_set_z_2exp (z, t, -x->e, rnd);
++ inex = mpfr_set_z_2exp (z, t, negxe, rnd);
+ mpz_clear (t);
+ return inex;
+ }
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-02-11 12:40:40.119363040 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-02-11 12:43:51.801257430 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p1";
++ return "4.1.0-p2";
+ }
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-02-11 12:46:49.075316772 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-02-11 12:46:49.115316335 +0000
+@@ -0,0 +1 @@
++set_z_2exp-overflow
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-02-11 12:43:51.801257430 +0000
++++ mpfr-4.1.0-b/VERSION 2021-02-11 12:46:49.115316335 +0000
+@@ -1 +1 @@
+-4.1.0-p2
++4.1.0-p3
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-02-11 12:43:51.801257430 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-02-11 12:46:49.115316335 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p2"
++#define MPFR_VERSION_STRING "4.1.0-p3"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+diff -Naurd mpfr-4.1.0-a/src/set_z_exp.c mpfr-4.1.0-b/src/set_z_exp.c
+--- mpfr-4.1.0-a/src/set_z_exp.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/set_z_exp.c 2021-02-11 12:46:49.103316466 +0000
+@@ -28,10 +28,11 @@
+ int
+ mpfr_set_z_2exp (mpfr_ptr f, mpz_srcptr z, mpfr_exp_t e, mpfr_rnd_t rnd_mode)
+ {
+- mp_size_t fn, zn, dif, en;
++ mp_size_t fn, zn, dif;
+ int k, sign_z, inex;
+ mp_limb_t *fp, *zp;
+- mpfr_exp_t exp;
++ mpfr_exp_t exp, nmax;
++ mpfr_uexp_t uexp;
+
+ sign_z = mpz_sgn (z);
+ if (MPFR_UNLIKELY (sign_z == 0)) /* ignore the exponent for 0 */
+@@ -43,10 +44,15 @@
+ MPFR_ASSERTD (sign_z == MPFR_SIGN_POS || sign_z == MPFR_SIGN_NEG);
+
+ zn = ABSIZ(z); /* limb size of z */
+- /* compute en = floor(e/GMP_NUMB_BITS) */
+- en = (e >= 0) ? e / GMP_NUMB_BITS : (e + 1) / GMP_NUMB_BITS - 1;
+ MPFR_ASSERTD (zn >= 1);
+- if (MPFR_UNLIKELY (zn + en > MPFR_EMAX_MAX / GMP_NUMB_BITS + 1))
++ nmax = MPFR_EMAX_MAX / GMP_NUMB_BITS + 1;
++ /* Detect early overflow with zn + en > nmax,
++ where en = floor(e / GMP_NUMB_BITS).
++ This is checked without an integer overflow (even assuming some
++ future version of GMP, where limitations may be removed). */
++ if (MPFR_UNLIKELY (e >= 0 ?
++ zn > nmax - e / GMP_NUMB_BITS :
++ zn + (e + 1) / GMP_NUMB_BITS - 1 > nmax))
+ return mpfr_overflow (f, rnd_mode, sign_z);
+ /* because zn + en >= MPFR_EMAX_MAX / GMP_NUMB_BITS + 2
+ implies (zn + en) * GMP_NUMB_BITS >= MPFR_EMAX_MAX + GMP_NUMB_BITS + 1
+@@ -64,8 +70,21 @@
+ and exp = zn * GMP_NUMB_BITS + e - k
+ <= (zn + en) * GMP_NUMB_BITS - k + GMP_NUMB_BITS - 1
+ <= MPFR_EMAX_MAX + 2 * GMP_NUMB_BITS - 1 */
+- exp = (mpfr_prec_t) zn * GMP_NUMB_BITS + e - k;
++ /* We need to compute exp = zn * GMP_NUMB_BITS + e - k with well-defined
++ operations (no integer overflows / no implementation-defined results).
++ The mathematical result of zn * GMP_NUMB_BITS may be larger than
++ the largest value of mpfr_exp_t while exp could still be less than
++ __gmpfr_emax. Thanks to early overflow detection, we can compute the
++ result in modular arithmetic, using mpfr_uexp_t, and convert it to
++ mpfr_exp_t. */
++ uexp = (mpfr_uexp_t) zn * GMP_NUMB_BITS + (mpfr_uexp_t) e - k;
++
++ /* Convert to signed in a portable way (see doc/README.dev).
++ On most platforms, this can be optimized to identity (no-op). */
++ exp = uexp > MPFR_EXP_MAX ? -1 - (mpfr_exp_t) ~uexp : (mpfr_exp_t) uexp;
++
+ /* The exponent will be exp or exp + 1 (due to rounding) */
++
+ if (MPFR_UNLIKELY (exp > __gmpfr_emax))
+ return mpfr_overflow (f, rnd_mode, sign_z);
+ if (MPFR_UNLIKELY (exp + 1 < __gmpfr_emin))
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-02-11 12:43:51.801257430 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-02-11 12:46:49.115316335 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p2";
++ return "4.1.0-p3";
+ }
+diff -Naurd mpfr-4.1.0-a/tests/tset_z_exp.c mpfr-4.1.0-b/tests/tset_z_exp.c
+--- mpfr-4.1.0-a/tests/tset_z_exp.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tset_z_exp.c 2021-02-11 12:46:49.103316466 +0000
+@@ -97,49 +97,149 @@
+ mpfr_get_si is a rather indirect test of a low level routine. */
+
+ static void
+-check (long i, mpfr_rnd_t rnd)
++check (long i, mpfr_rnd_t rnd, int reduced)
+ {
+- mpfr_t f;
++ mpfr_t f1, f2, f3;
+ mpz_t z;
+- mpfr_exp_t e;
++ mpfr_exp_t e, old_emin, old_emax;
+ int inex;
++ mpfr_flags_t flags;
++
++ old_emin = mpfr_get_emin ();
++ old_emax = mpfr_get_emax ();
+
+ /* using CHAR_BIT * sizeof(long) bits of precision ensures that
+ mpfr_set_z_2exp is exact below */
+- mpfr_init2 (f, CHAR_BIT * sizeof(long));
++ mpfr_inits2 (CHAR_BIT * sizeof(long), f1, f2, f3, (mpfr_ptr) 0);
+ mpz_init (z);
+ mpz_set_ui (z, i);
+ /* the following loop ensures that no overflow occurs */
+ do
+ e = randexp ();
+ while (e > mpfr_get_emax () - CHAR_BIT * sizeof(long));
+- inex = mpfr_set_z_2exp (f, z, e, rnd);
+- if (inex != 0)
++
++ mpfr_clear_flags ();
++ inex = mpfr_set_z_2exp (f1, z, e, rnd);
++ flags = __gmpfr_flags;
++
++ if (inex != 0 || flags != 0 ||
++ (mpfr_div_2si (f2, f1, e, rnd), mpfr_get_si (f2, MPFR_RNDZ) != i))
+ {
+- printf ("Error in mpfr_set_z_2exp for i=%ld, e=%ld,"
+- " wrong ternary value\n", i, (long) e);
+- printf ("expected 0, got %d\n", inex);
++ printf ("Error in mpfr_set_z_2exp for i=%ld e=%" MPFR_EXP_FSPEC
++ "d rnd_mode=%d\n", i, (mpfr_eexp_t) e, rnd);
++ mpfr_set_si_2exp (f2, i, e, MPFR_RNDN);
++ printf ("expected "); mpfr_dump (f2);
++ printf ("with inex = %d and flags =", 0);
++ flags_out (0);
++ printf ("got "); mpfr_dump (f1);
++ printf ("with inex = %d and flags =", inex);
++ flags_out (flags);
+ exit (1);
+ }
+- mpfr_div_2si (f, f, e, rnd);
+- if (mpfr_get_si (f, MPFR_RNDZ) != i)
++
++ if (reduced)
+ {
+- printf ("Error in mpfr_set_z_2exp for i=%ld e=", i);
+- if (e < LONG_MIN)
+- printf ("(<LONG_MIN)");
+- else if (e > LONG_MAX)
+- printf ("(>LONG_MAX)");
+- else
+- printf ("%ld", (long) e);
+- printf (" rnd_mode=%d\n", rnd);
+- printf ("expected %ld\n", i);
+- printf ("got "); mpfr_dump (f);
+- exit (1);
++ mpfr_exp_t ef, emin, emax;
++ int inex2, inex3;
++ mpfr_flags_t flags2, flags3;
++
++ ef = i == 0 ? 0 : mpfr_get_exp (f1);
++ for (emin = ef - 2; emin <= ef + 2; emin++)
++ for (emax = emin; emax <= ef + 2; emax++)
++ {
++ inex3 = mpfr_set (f3, f1, rnd);
++ MPFR_ASSERTN (inex3 == 0);
++ mpfr_set_emin (emin);
++ mpfr_set_emax (emax);
++ mpfr_clear_flags ();
++ inex2 = mpfr_set_z_2exp (f2, z, e, rnd);
++ flags2 = __gmpfr_flags;
++ mpfr_clear_flags ();
++ inex3 = mpfr_check_range (f3, 0, rnd);
++ flags3 = __gmpfr_flags;
++ if (!(mpfr_equal_p (f2, f3) &&
++ SAME_SIGN (inex2, inex3) &&
++ flags2 == flags3))
++ {
++ printf ("Error in mpfr_set_z_2exp for i=%ld e=%"
++ MPFR_EXP_FSPEC "d rnd_mode=%d\nand emin=%"
++ MPFR_EXP_FSPEC "d emax=%" MPFR_EXP_FSPEC
++ "d\n", i, (mpfr_eexp_t) e, rnd,
++ (mpfr_eexp_t) emin, (mpfr_eexp_t) emax);
++ printf ("expected "); mpfr_dump (f3);
++ printf ("with inex = %d and flags =", inex3);
++ flags_out (flags3);
++ printf ("got "); mpfr_dump (f2);
++ printf ("with inex = %d and flags =", inex2);
++ flags_out (flags2);
++ exit (1);
++ }
++ }
++ mpfr_set_emin (old_emin);
++ mpfr_set_emax (old_emax);
+ }
+- mpfr_clear (f);
++
++ mpfr_clears (f1, f2, f3, (mpfr_ptr) 0);
+ mpz_clear (z);
+ }
+
++static void
++check_huge (void)
++{
++ if (getenv ("MPFR_CHECK_LARGEMEM") != NULL)
++ {
++ mpfr_t x;
++ mpz_t z;
++ long e;
++
++ /* Increase tests_memory_limit to the maximum in order to avoid
++ an obvious failure due to insufficient memory. */
++ tests_memory_limit = (size_t) -1; /* no memory limit */
++
++ mpfr_init2 (x, 32);
++
++ /* In r14140, with a 32-bit ABI (GCC's -m32):
++ - With UBsan (-fsanitize=undefined -fno-sanitize-recover),
++ this fails with:
++ set_z_2exp.c:71:26: runtime error: signed integer overflow:
++ 67108864 * 32 cannot be represented in type 'long int'
++ - With -D_MPFR_EXP_FORMAT=4, this fails with:
++ Expected 0.10001000000000000000000000000000E5
++ Got 0
++ */
++ mpz_init_set_ui (z, 17);
++ e = 0x7ffffff0;
++ mpz_mul_2exp (z, z, e);
++ mpz_add_ui (z, z, 1);
++ mpfr_set_z_2exp (x, z, -e, MPFR_RNDN);
++ if (mpfr_cmp_ui0 (x, 17) != 0)
++ {
++ printf ("Error 1 in check_huge\n");
++ printf ("Expected 0.10001000000000000000000000000000E5\n");
++ printf ("Got ");
++ mpfr_dump (x);
++ exit (1);
++ }
++ mpz_clear (z);
++
++ mpz_init_set_ui (z, 17);
++ mpz_mul_2exp (z, z, 0xffffffb0);
++ mpz_add_ui (z, z, 1);
++ mpfr_set_z_2exp (x, z, -1, MPFR_RNDN);
++ if (! MPFR_IS_INF (x) || MPFR_IS_NEG (x))
++ {
++ printf ("Error 2 in check_huge\n");
++ printf ("Expected @Inf@\n");
++ printf ("Got ");
++ mpfr_dump (x);
++ exit (1);
++ }
++ mpz_clear (z);
++
++ mpfr_clear (x);
++ }
++}
++
+ int
+ main (int argc, char *argv[])
+ {
+@@ -147,11 +247,13 @@
+
+ tests_start_mpfr ();
+
+- check (0, MPFR_RNDN);
++ check (0, MPFR_RNDN, 0);
+ for (j = 0; j < 200000; j++)
+- check (randlimb () & LONG_MAX, RND_RAND ());
++ check (randlimb () & LONG_MAX, RND_RAND (), j < 200);
+ check0 ();
+
++ check_huge ();
++
+ tests_end_mpfr ();
+
+ return 0;
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-02-11 12:48:27.322243271 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-02-11 12:48:27.370242746 +0000
+@@ -0,0 +1 @@
++prototypes
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-02-11 12:46:49.115316335 +0000
++++ mpfr-4.1.0-b/VERSION 2021-02-11 12:48:27.370242746 +0000
+@@ -1 +1 @@
+-4.1.0-p3
++4.1.0-p4
+diff -Naurd mpfr-4.1.0-a/src/atan.c mpfr-4.1.0-b/src/atan.c
+--- mpfr-4.1.0-a/src/atan.c 2020-04-22 15:27:07.000000000 +0000
++++ mpfr-4.1.0-b/src/atan.c 2021-02-11 12:48:27.354242922 +0000
+@@ -56,7 +56,7 @@
+ };
+
+ static void
+-set_table (mpfr_t y, const mp_limb_t x[3])
++set_table (mpfr_ptr y, const mp_limb_t x[3])
+ {
+ mpfr_prec_t p = MPFR_PREC(y);
+ mp_size_t n = MPFR_PREC2LIMBS(p);
+diff -Naurd mpfr-4.1.0-a/src/const_euler.c mpfr-4.1.0-b/src/const_euler.c
+--- mpfr-4.1.0-a/src/const_euler.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/const_euler.c 2021-02-11 12:48:27.354242922 +0000
+@@ -181,7 +181,7 @@
+ }
+
+ int
+-mpfr_const_euler_internal (mpfr_t x, mpfr_rnd_t rnd)
++mpfr_const_euler_internal (mpfr_ptr x, mpfr_rnd_t rnd)
+ {
+ mpfr_const_euler_bs_t sum;
+ mpz_t t, u, v;
+diff -Naurd mpfr-4.1.0-a/src/eint.c mpfr-4.1.0-b/src/eint.c
+--- mpfr-4.1.0-a/src/eint.c 2020-03-09 15:31:45.000000000 +0000
++++ mpfr-4.1.0-b/src/eint.c 2021-02-11 12:48:27.354242922 +0000
+@@ -36,7 +36,7 @@
+ Return PREC(y) when the truncated series does not converge.
+ */
+ static mpfr_exp_t
+-mpfr_eint_aux (mpfr_t y, mpfr_srcptr x)
++mpfr_eint_aux (mpfr_ptr y, mpfr_srcptr x)
+ {
+ mpfr_t eps; /* dynamic (absolute) error bound on t */
+ mpfr_t erru, errs;
+diff -Naurd mpfr-4.1.0-a/src/erandom.c mpfr-4.1.0-b/src/erandom.c
+--- mpfr-4.1.0-a/src/erandom.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/erandom.c 2021-02-11 12:48:27.354242922 +0000
+@@ -80,7 +80,7 @@
+
+ /* return an exponential random deviate with mean 1 as a MPFR */
+ int
+-mpfr_erandom (mpfr_t z, gmp_randstate_t r, mpfr_rnd_t rnd)
++mpfr_erandom (mpfr_ptr z, gmp_randstate_t r, mpfr_rnd_t rnd)
+ {
+ mpfr_random_deviate_t x, p, q;
+ int inex;
+diff -Naurd mpfr-4.1.0-a/src/fpif.c mpfr-4.1.0-b/src/fpif.c
+--- mpfr-4.1.0-a/src/fpif.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/fpif.c 2021-02-11 12:48:27.354242922 +0000
+@@ -291,7 +291,8 @@
+ * until one has integer types larger than 128 bits).
+ */
+ static unsigned char*
+-mpfr_fpif_store_exponent (unsigned char *buffer, size_t *buffer_size, mpfr_t x)
++mpfr_fpif_store_exponent (unsigned char *buffer, size_t *buffer_size,
++ mpfr_ptr x)
+ {
+ unsigned char *result;
+ mpfr_uexp_t uexp;
+@@ -372,7 +373,7 @@
+ * than 128 bits).
+ */
+ static int
+-mpfr_fpif_read_exponent_from_file (mpfr_t x, FILE * fh)
++mpfr_fpif_read_exponent_from_file (mpfr_ptr x, FILE * fh)
+ {
+ mpfr_exp_t exponent;
+ mpfr_uexp_t uexp;
+@@ -456,7 +457,7 @@
+ * format
+ */
+ static unsigned char*
+-mpfr_fpif_store_limbs (unsigned char *buffer, size_t *buffer_size, mpfr_t x)
++mpfr_fpif_store_limbs (unsigned char *buffer, size_t *buffer_size, mpfr_ptr x)
+ {
+ unsigned char *result;
+ mpfr_prec_t precision;
+@@ -492,7 +493,7 @@
+ * Assume buffer is not NULL.
+ */
+ static void
+-mpfr_fpif_read_limbs (mpfr_t x, unsigned char *buffer, size_t nb_byte)
++mpfr_fpif_read_limbs (mpfr_ptr x, unsigned char *buffer, size_t nb_byte)
+ {
+ size_t mp_bytes_per_limb;
+ size_t nb_partial_byte;
+@@ -522,7 +523,7 @@
+ * return 0 if successful
+ */
+ int
+-mpfr_fpif_export (FILE *fh, mpfr_t x)
++mpfr_fpif_export (FILE *fh, mpfr_ptr x)
+ {
+ int status;
+ unsigned char *buf;
+@@ -582,7 +583,7 @@
+ * Return 0 if the import was successful.
+ */
+ int
+-mpfr_fpif_import (mpfr_t x, FILE *fh)
++mpfr_fpif_import (mpfr_ptr x, FILE *fh)
+ {
+ int status;
+ mpfr_prec_t precision;
+diff -Naurd mpfr-4.1.0-a/src/li2.c mpfr-4.1.0-b/src/li2.c
+--- mpfr-4.1.0-a/src/li2.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/li2.c 2021-02-11 12:48:27.354242922 +0000
+@@ -31,7 +31,7 @@
+ for determinating the relative error.
+ */
+ static int
+-li2_series (mpfr_t sum, mpfr_srcptr z, mpfr_rnd_t rnd_mode)
++li2_series (mpfr_ptr sum, mpfr_srcptr z, mpfr_rnd_t rnd_mode)
+ {
+ int i;
+ mpfr_t s, u, v, w;
+diff -Naurd mpfr-4.1.0-a/src/lngamma.c mpfr-4.1.0-b/src/lngamma.c
+--- mpfr-4.1.0-a/src/lngamma.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/lngamma.c 2021-02-11 12:48:27.354242922 +0000
+@@ -31,7 +31,7 @@
+ precision should be >= 4.
+ */
+ static void
+-mpfr_gamma_alpha (mpfr_t s, mpfr_prec_t p)
++mpfr_gamma_alpha (mpfr_ptr s, mpfr_prec_t p)
+ {
+ MPFR_LOG_FUNC
+ (("p=%Pu", p),
+diff -Naurd mpfr-4.1.0-a/src/mpfr-impl.h mpfr-4.1.0-b/src/mpfr-impl.h
+--- mpfr-4.1.0-a/src/mpfr-impl.h 2020-06-10 21:50:12.000000000 +0000
++++ mpfr-4.1.0-b/src/mpfr-impl.h 2021-02-11 12:48:27.354242922 +0000
+@@ -2474,7 +2474,8 @@
+ __MPFR_DECLSPEC mpz_srcptr mpfr_bernoulli_cache (unsigned long);
+ __MPFR_DECLSPEC void mpfr_bernoulli_freecache (void);
+
+-__MPFR_DECLSPEC int mpfr_sincos_fast (mpfr_t, mpfr_t, mpfr_srcptr, mpfr_rnd_t);
++__MPFR_DECLSPEC int mpfr_sincos_fast (mpfr_ptr, mpfr_ptr, mpfr_srcptr,
++ mpfr_rnd_t);
+
+ __MPFR_DECLSPEC double mpfr_scale2 (double, int);
+
+@@ -2485,7 +2486,7 @@
+ mpfr_prec_t);
+
+ __MPFR_DECLSPEC void mpfr_mpz_init (mpz_ptr);
+-__MPFR_DECLSPEC void mpfr_mpz_init2 (mpz_t, mp_bitcnt_t);
++__MPFR_DECLSPEC void mpfr_mpz_init2 (mpz_ptr, mp_bitcnt_t);
+ __MPFR_DECLSPEC void mpfr_mpz_clear (mpz_ptr);
+
+ __MPFR_DECLSPEC int mpfr_odd_p (mpfr_srcptr);
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-02-11 12:46:49.115316335 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-02-11 12:48:27.366242791 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p3"
++#define MPFR_VERSION_STRING "4.1.0-p4"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+@@ -781,8 +781,8 @@
+ __MPFR_DECLSPEC int mpfr_strtofr (mpfr_ptr, const char *, char **, int,
+ mpfr_rnd_t);
+
+-__MPFR_DECLSPEC void mpfr_round_nearest_away_begin (mpfr_t);
+-__MPFR_DECLSPEC int mpfr_round_nearest_away_end (mpfr_t, int);
++__MPFR_DECLSPEC void mpfr_round_nearest_away_begin (mpfr_ptr);
++__MPFR_DECLSPEC int mpfr_round_nearest_away_end (mpfr_ptr, int);
+
+ __MPFR_DECLSPEC size_t mpfr_custom_get_size (mpfr_prec_t);
+ __MPFR_DECLSPEC void mpfr_custom_init (void *, mpfr_prec_t);
+@@ -1080,10 +1080,12 @@
+ #define mpfr_set_uj_2exp __gmpfr_set_uj_2exp
+ #define mpfr_get_sj __gmpfr_mpfr_get_sj
+ #define mpfr_get_uj __gmpfr_mpfr_get_uj
+-__MPFR_DECLSPEC int mpfr_set_sj (mpfr_t, intmax_t, mpfr_rnd_t);
+-__MPFR_DECLSPEC int mpfr_set_sj_2exp (mpfr_t, intmax_t, intmax_t, mpfr_rnd_t);
+-__MPFR_DECLSPEC int mpfr_set_uj (mpfr_t, uintmax_t, mpfr_rnd_t);
+-__MPFR_DECLSPEC int mpfr_set_uj_2exp (mpfr_t, uintmax_t, intmax_t, mpfr_rnd_t);
++__MPFR_DECLSPEC int mpfr_set_sj (mpfr_ptr, intmax_t, mpfr_rnd_t);
++__MPFR_DECLSPEC int mpfr_set_sj_2exp (mpfr_ptr, intmax_t, intmax_t,
++ mpfr_rnd_t);
++__MPFR_DECLSPEC int mpfr_set_uj (mpfr_ptr, uintmax_t, mpfr_rnd_t);
++__MPFR_DECLSPEC int mpfr_set_uj_2exp (mpfr_ptr, uintmax_t, intmax_t,
++ mpfr_rnd_t);
+ __MPFR_DECLSPEC intmax_t mpfr_get_sj (mpfr_srcptr, mpfr_rnd_t);
+ __MPFR_DECLSPEC uintmax_t mpfr_get_uj (mpfr_srcptr, mpfr_rnd_t);
+
+diff -Naurd mpfr-4.1.0-a/src/nrandom.c mpfr-4.1.0-b/src/nrandom.c
+--- mpfr-4.1.0-a/src/nrandom.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/nrandom.c 2021-02-11 12:48:27.354242922 +0000
+@@ -155,7 +155,7 @@
+
+ /* return a normal random deviate with mean 0 and variance 1 as a MPFR */
+ int
+-mpfr_nrandom (mpfr_t z, gmp_randstate_t r, mpfr_rnd_t rnd)
++mpfr_nrandom (mpfr_ptr z, gmp_randstate_t r, mpfr_rnd_t rnd)
+ {
+ mpfr_random_deviate_t x, p, q;
+ int inex;
+diff -Naurd mpfr-4.1.0-a/src/pool.c mpfr-4.1.0-b/src/pool.c
+--- mpfr-4.1.0-a/src/pool.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/pool.c 2021-02-11 12:48:27.354242922 +0000
+@@ -35,7 +35,7 @@
+ static MPFR_THREAD_ATTR __mpz_struct mpz_tab[MPFR_POOL_NENTRIES];
+
+ MPFR_HOT_FUNCTION_ATTR void
+-mpfr_mpz_init (mpz_t z)
++mpfr_mpz_init (mpz_ptr z)
+ {
+ if (MPFR_LIKELY (n_alloc > 0))
+ {
+@@ -54,7 +54,7 @@
+ }
+
+ MPFR_HOT_FUNCTION_ATTR void
+-mpfr_mpz_init2 (mpz_t z, mp_bitcnt_t n)
++mpfr_mpz_init2 (mpz_ptr z, mp_bitcnt_t n)
+ {
+ /* The condition on n is used below as the argument n will be ignored if
+ the mpz_t is obtained from the MPFR stack of previously used mpz_t.
+@@ -82,7 +82,7 @@
+
+
+ MPFR_HOT_FUNCTION_ATTR void
+-mpfr_mpz_clear (mpz_t z)
++mpfr_mpz_clear (mpz_ptr z)
+ {
+ /* We only put objects with at most MPFR_POOL_MAX_SIZE in the mpz_t pool,
+ to avoid it takes too much memory (and anyway the speedup is mainly
+diff -Naurd mpfr-4.1.0-a/src/random_deviate.c mpfr-4.1.0-b/src/random_deviate.c
+--- mpfr-4.1.0-a/src/random_deviate.c 2021-02-11 12:43:51.789257562 +0000
++++ mpfr-4.1.0-b/src/random_deviate.c 2021-02-11 12:48:27.354242922 +0000
+@@ -64,7 +64,7 @@
+
+ /* allocate and set to (0,1) */
+ void
+-mpfr_random_deviate_init (mpfr_random_deviate_t x)
++mpfr_random_deviate_init (mpfr_random_deviate_ptr x)
+ {
+ mpz_init (x->f);
+ x->e = 0;
+@@ -72,21 +72,22 @@
+
+ /* reset to (0,1) */
+ void
+-mpfr_random_deviate_reset (mpfr_random_deviate_t x)
++mpfr_random_deviate_reset (mpfr_random_deviate_ptr x)
+ {
+ x->e = 0;
+ }
+
+ /* deallocate */
+ void
+-mpfr_random_deviate_clear (mpfr_random_deviate_t x)
++mpfr_random_deviate_clear (mpfr_random_deviate_ptr x)
+ {
+ mpz_clear (x->f);
+ }
+
+ /* swap two random deviates */
+ void
+-mpfr_random_deviate_swap (mpfr_random_deviate_t x, mpfr_random_deviate_t y)
++mpfr_random_deviate_swap (mpfr_random_deviate_ptr x,
++ mpfr_random_deviate_ptr y)
+ {
+ mpfr_random_size_t s;
+ unsigned long t;
+@@ -107,7 +108,7 @@
+
+ /* ensure x has at least k bits */
+ static void
+-random_deviate_generate (mpfr_random_deviate_t x, mpfr_random_size_t k,
++random_deviate_generate (mpfr_random_deviate_ptr x, mpfr_random_size_t k,
+ gmp_randstate_t r, mpz_t t)
+ {
+ /* Various compile time checks on mpfr_random_deviate_t */
+@@ -223,7 +224,7 @@
+
+ /* return position of leading bit, counting from 1 */
+ static mpfr_random_size_t
+-random_deviate_leading_bit (mpfr_random_deviate_t x, gmp_randstate_t r)
++random_deviate_leading_bit (mpfr_random_deviate_ptr x, gmp_randstate_t r)
+ {
+ mpfr_random_size_t l;
+ random_deviate_generate (x, W, r, 0);
+@@ -243,7 +244,7 @@
+
+ /* return kth bit of fraction, representing 2^-k */
+ int
+-mpfr_random_deviate_tstbit (mpfr_random_deviate_t x, mpfr_random_size_t k,
++mpfr_random_deviate_tstbit (mpfr_random_deviate_ptr x, mpfr_random_size_t k,
+ gmp_randstate_t r)
+ {
+ if (k == 0)
+@@ -256,7 +257,8 @@
+
+ /* compare two random deviates, x < y */
+ int
+-mpfr_random_deviate_less (mpfr_random_deviate_t x, mpfr_random_deviate_t y,
++mpfr_random_deviate_less (mpfr_random_deviate_ptr x,
++ mpfr_random_deviate_ptr y,
+ gmp_randstate_t r)
+ {
+ mpfr_random_size_t k = 1;
+@@ -280,7 +282,7 @@
+ /* set mpfr_t z = (neg ? -1 : 1) * (n + x) */
+ int
+ mpfr_random_deviate_value (int neg, unsigned long n,
+- mpfr_random_deviate_t x, mpfr_t z,
++ mpfr_random_deviate_ptr x, mpfr_ptr z,
+ gmp_randstate_t r, mpfr_rnd_t rnd)
+ {
+ /* r is used to add as many bits as necessary to match the precision of z */
+diff -Naurd mpfr-4.1.0-a/src/random_deviate.h mpfr-4.1.0-b/src/random_deviate.h
+--- mpfr-4.1.0-a/src/random_deviate.h 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/random_deviate.h 2021-02-11 12:48:27.354242922 +0000
+@@ -76,7 +76,7 @@
+ /* set mpfr_t z = (neg ? -1 : 1) * (n + x) */
+ __MPFR_DECLSPEC int
+ mpfr_random_deviate_value (int, unsigned long,
+- mpfr_random_deviate_ptr, mpfr_t,
++ mpfr_random_deviate_ptr, mpfr_ptr,
+ gmp_randstate_t, mpfr_rnd_t);
+
+ #if defined(__cplusplus)
+diff -Naurd mpfr-4.1.0-a/src/rndna.c mpfr-4.1.0-b/src/rndna.c
+--- mpfr-4.1.0-a/src/rndna.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/rndna.c 2021-02-11 12:48:27.354242922 +0000
+@@ -61,7 +61,7 @@
+ and prepares rop to give it one more bit of precision
+ and to save its old value within it. */
+ void
+-mpfr_round_nearest_away_begin (mpfr_t rop)
++mpfr_round_nearest_away_begin (mpfr_ptr rop)
+ {
+ mpfr_t tmp;
+ mp_size_t xsize;
+@@ -129,7 +129,7 @@
+ copying it back the result of the applied function
+ and performing additional roundings. */
+ int
+-mpfr_round_nearest_away_end (mpfr_t rop, int inex)
++mpfr_round_nearest_away_end (mpfr_ptr rop, int inex)
+ {
+ mpfr_t tmp;
+ mp_size_t xsize;
+diff -Naurd mpfr-4.1.0-a/src/set_sj.c mpfr-4.1.0-b/src/set_sj.c
+--- mpfr-4.1.0-a/src/set_sj.c 2020-06-01 10:39:52.000000000 +0000
++++ mpfr-4.1.0-b/src/set_sj.c 2021-02-11 12:48:27.354242922 +0000
+@@ -26,13 +26,13 @@
+ #ifdef _MPFR_H_HAVE_INTMAX_T
+
+ int
+-mpfr_set_sj (mpfr_t x, intmax_t j, mpfr_rnd_t rnd)
++mpfr_set_sj (mpfr_ptr x, intmax_t j, mpfr_rnd_t rnd)
+ {
+ return mpfr_set_sj_2exp (x, j, 0, rnd);
+ }
+
+ int
+-mpfr_set_sj_2exp (mpfr_t x, intmax_t j, intmax_t e, mpfr_rnd_t rnd)
++mpfr_set_sj_2exp (mpfr_ptr x, intmax_t j, intmax_t e, mpfr_rnd_t rnd)
+ {
+ if (j >= 0)
+ return mpfr_set_uj_2exp (x, j, e, rnd);
+diff -Naurd mpfr-4.1.0-a/src/set_str.c mpfr-4.1.0-b/src/set_str.c
+--- mpfr-4.1.0-a/src/set_str.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/set_str.c 2021-02-11 12:48:27.354242922 +0000
+@@ -23,7 +23,7 @@
+ #include "mpfr-impl.h"
+
+ int
+-mpfr_set_str (mpfr_t x, const char *str, int base, mpfr_rnd_t rnd)
++mpfr_set_str (mpfr_ptr x, const char *str, int base, mpfr_rnd_t rnd)
+ {
+ char *p;
+
+diff -Naurd mpfr-4.1.0-a/src/set_uj.c mpfr-4.1.0-b/src/set_uj.c
+--- mpfr-4.1.0-a/src/set_uj.c 2020-06-01 10:39:52.000000000 +0000
++++ mpfr-4.1.0-b/src/set_uj.c 2021-02-11 12:48:27.354242922 +0000
+@@ -29,13 +29,13 @@
+ #define uintmaxpml (sizeof(uintmax_t) / sizeof(mp_limb_t))
+
+ int
+-mpfr_set_uj (mpfr_t x, uintmax_t j, mpfr_rnd_t rnd)
++mpfr_set_uj (mpfr_ptr x, uintmax_t j, mpfr_rnd_t rnd)
+ {
+ return mpfr_set_uj_2exp (x, j, 0, rnd);
+ }
+
+ int
+-mpfr_set_uj_2exp (mpfr_t x, uintmax_t j, intmax_t e, mpfr_rnd_t rnd)
++mpfr_set_uj_2exp (mpfr_ptr x, uintmax_t j, intmax_t e, mpfr_rnd_t rnd)
+ {
+ int cnt, inex;
+ mp_size_t i, k;
+diff -Naurd mpfr-4.1.0-a/src/sin_cos.c mpfr-4.1.0-b/src/sin_cos.c
+--- mpfr-4.1.0-a/src/sin_cos.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/sin_cos.c 2021-02-11 12:48:27.354242922 +0000
+@@ -463,7 +463,7 @@
+ Return err such that the relative error is bounded by 2^err ulps.
+ */
+ static int
+-sincos_aux (mpfr_t s, mpfr_t c, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
++sincos_aux (mpfr_ptr s, mpfr_ptr c, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
+ {
+ mpfr_prec_t prec_s, sh;
+ mpz_t Q, S, C, Q2, S2, C2, y;
+@@ -577,7 +577,7 @@
+ Assumes s differs from c.
+ */
+ int
+-mpfr_sincos_fast (mpfr_t s, mpfr_t c, mpfr_srcptr x, mpfr_rnd_t rnd)
++mpfr_sincos_fast (mpfr_ptr s, mpfr_ptr c, mpfr_srcptr x, mpfr_rnd_t rnd)
+ {
+ int inexs, inexc;
+ mpfr_t x_red, ts, tc;
+diff -Naurd mpfr-4.1.0-a/src/strtofr.c mpfr-4.1.0-b/src/strtofr.c
+--- mpfr-4.1.0-a/src/strtofr.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/strtofr.c 2021-02-11 12:48:27.354242922 +0000
+@@ -226,7 +226,7 @@
+ BUT if it returns 0 (NAN or INF), the ternary value is also '0'
+ (ie NAN and INF are exact) */
+ static int
+-parse_string (mpfr_t x, struct parsed_string *pstr,
++parse_string (mpfr_ptr x, struct parsed_string *pstr,
+ const char **string, int base)
+ {
+ const char *str = *string;
+@@ -451,7 +451,7 @@
+ and the precision of x.
+ Returns the ternary value. */
+ static int
+-parsed_string_to_mpfr (mpfr_t x, struct parsed_string *pstr, mpfr_rnd_t rnd)
++parsed_string_to_mpfr (mpfr_ptr x, struct parsed_string *pstr, mpfr_rnd_t rnd)
+ {
+ mpfr_prec_t precx, prec, ysize_bits, pstr_size;
+ mpfr_exp_t exp;
+@@ -934,7 +934,7 @@
+ }
+
+ int
+-mpfr_strtofr (mpfr_t x, const char *string, char **end, int base,
++mpfr_strtofr (mpfr_ptr x, const char *string, char **end, int base,
+ mpfr_rnd_t rnd)
+ {
+ int res;
+diff -Naurd mpfr-4.1.0-a/src/vasprintf.c mpfr-4.1.0-b/src/vasprintf.c
+--- mpfr-4.1.0-a/src/vasprintf.c 2020-06-01 10:39:52.000000000 +0000
++++ mpfr-4.1.0-b/src/vasprintf.c 2021-02-11 12:48:27.354242922 +0000
+@@ -963,7 +963,7 @@
+ #define NDIGITS 8
+
+ MPFR_RETURNS_NONNULL static char *
+-mpfr_get_str_wrapper (mpfr_exp_t *exp, int base, size_t n, const mpfr_t op,
++mpfr_get_str_wrapper (mpfr_exp_t *exp, int base, size_t n, mpfr_srcptr op,
+ const struct printf_spec spec)
+ {
+ size_t ndigits;
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-02-11 12:46:49.115316335 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-02-11 12:48:27.370242746 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p3";
++ return "4.1.0-p4";
+ }
+diff -Naurd mpfr-4.1.0-a/src/zeta.c mpfr-4.1.0-b/src/zeta.c
+--- mpfr-4.1.0-a/src/zeta.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/src/zeta.c 2021-02-11 12:48:27.354242922 +0000
+@@ -35,7 +35,7 @@
+ sum(tc[i]*product((s+2j)*(s+2j-1)/n^2,j=1..i-1), i=1..p)*s*n^(-s-1)
+ */
+ static void
+-mpfr_zeta_part_b (mpfr_t b, mpfr_srcptr s, int n, int p, mpfr_t *tc)
++mpfr_zeta_part_b (mpfr_ptr b, mpfr_srcptr s, int n, int p, mpfr_t *tc)
+ {
+ mpfr_t s1, d, u;
+ unsigned long n2;
+@@ -130,7 +130,7 @@
+ n - an integer
+ Output: sum - a floating-point number approximating sum(1/i^s, i=1..n-1) */
+ static void
+-mpfr_zeta_part_a (mpfr_t sum, mpfr_srcptr s, int n)
++mpfr_zeta_part_a (mpfr_ptr sum, mpfr_srcptr s, int n)
+ {
+ mpfr_t u, s1;
+ int i;
+@@ -158,7 +158,7 @@
+ Output: z - Zeta(s) rounded to the precision of z with direction rnd_mode
+ */
+ static int
+-mpfr_zeta_pos (mpfr_t z, mpfr_srcptr s, mpfr_rnd_t rnd_mode)
++mpfr_zeta_pos (mpfr_ptr z, mpfr_srcptr s, mpfr_rnd_t rnd_mode)
+ {
+ mpfr_t b, c, z_pre, f, s1;
+ double beta, sd, dnep;
+@@ -356,8 +356,8 @@
+ At input, p is Pi rounded down.
+ The comments in the code are for rnd = RNDD. */
+ static void
+-mpfr_reflection_overflow (mpfr_t z, mpfr_t s1, const mpfr_t s, mpfr_t y,
+- mpfr_t p, mpfr_rnd_t rnd)
++mpfr_reflection_overflow (mpfr_ptr z, mpfr_ptr s1, mpfr_srcptr s, mpfr_ptr y,
++ mpfr_ptr p, mpfr_rnd_t rnd)
+ {
+ mpz_t sint;
+
+@@ -432,7 +432,7 @@
+ }
+
+ int
+-mpfr_zeta (mpfr_t z, mpfr_srcptr s, mpfr_rnd_t rnd_mode)
++mpfr_zeta (mpfr_ptr z, mpfr_srcptr s, mpfr_rnd_t rnd_mode)
+ {
+ mpfr_t z_pre, s1, y, p;
+ long add;
+diff -Naurd mpfr-4.1.0-a/tests/tcmp2.c mpfr-4.1.0-b/tests/tcmp2.c
+--- mpfr-4.1.0-a/tests/tcmp2.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tcmp2.c 2021-02-11 12:48:27.350242965 +0000
+@@ -24,7 +24,7 @@
+
+ /* set bit n of x to b, where bit 0 is the most significant one */
+ static void
+-set_bit (mpfr_t x, unsigned int n, int b)
++set_bit (mpfr_ptr x, unsigned int n, int b)
+ {
+ unsigned l;
+ mp_size_t xn;
+diff -Naurd mpfr-4.1.0-a/tests/tdiv.c mpfr-4.1.0-b/tests/tdiv.c
+--- mpfr-4.1.0-a/tests/tdiv.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tdiv.c 2021-02-11 12:48:27.350242965 +0000
+@@ -369,7 +369,7 @@
+ /* given y = o(x/u), x, u, find the inexact flag by
+ multiplying y by u */
+ static int
+-get_inexact (mpfr_t y, mpfr_t x, mpfr_t u)
++get_inexact (mpfr_ptr y, mpfr_ptr x, mpfr_ptr u)
+ {
+ mpfr_t xx;
+ int inex;
+diff -Naurd mpfr-4.1.0-a/tests/teq.c mpfr-4.1.0-b/tests/teq.c
+--- mpfr-4.1.0-a/tests/teq.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/teq.c 2021-02-11 12:48:27.350242965 +0000
+@@ -23,7 +23,7 @@
+ #include "mpfr-test.h"
+
+ static void
+-teq (mpfr_t x)
++teq (mpfr_ptr x)
+ {
+ mpfr_t y;
+ unsigned long k, px, mx;
+diff -Naurd mpfr-4.1.0-a/tests/terandom_chisq.c mpfr-4.1.0-b/tests/terandom_chisq.c
+--- mpfr-4.1.0-a/tests/terandom_chisq.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/terandom_chisq.c 2021-02-11 12:48:27.350242965 +0000
+@@ -26,7 +26,7 @@
+ * exponential distribution. We only take differences of this function so the
+ * offset doesn't matter; here Phi(0) = 0. */
+ static void
+-exponential_cumulative (mpfr_t z, mpfr_t x, mpfr_rnd_t rnd)
++exponential_cumulative (mpfr_ptr z, mpfr_ptr x, mpfr_rnd_t rnd)
+ {
+ mpfr_neg (z, x, rnd);
+ mpfr_expm1 (z, z, rnd);
+@@ -43,7 +43,7 @@
+ * TAOCP, Vol 2, 3.3.1, Table 1. It more accurate than the similar formula,
+ * DLMF 8.11.10. */
+ static void
+-chisq_prob (mpfr_t q, long nu, mpfr_t chisqp)
++chisq_prob (mpfr_ptr q, long nu, mpfr_ptr chisqp)
+ {
+ mpfr_t t;
+ mpfr_rnd_t rnd;
+@@ -170,7 +170,7 @@
+ * this function. low precision means prec = 2, 3, or 4. High values of
+ * precision will result in integer overflow. */
+ static long
+-sequential (mpfr_t x)
++sequential (mpfr_ptr x)
+ {
+ long expt, prec;
+
+diff -Naurd mpfr-4.1.0-a/tests/tfmma.c mpfr-4.1.0-b/tests/tfmma.c
+--- mpfr-4.1.0-a/tests/tfmma.c 2020-03-24 13:47:38.000000000 +0000
++++ mpfr-4.1.0-b/tests/tfmma.c 2021-02-11 12:48:27.350242965 +0000
+@@ -24,7 +24,7 @@
+
+ /* check both mpfr_fmma and mpfr_fmms */
+ static void
+-random_test (mpfr_t a, mpfr_t b, mpfr_t c, mpfr_t d, mpfr_rnd_t rnd)
++random_test (mpfr_ptr a, mpfr_ptr b, mpfr_ptr c, mpfr_ptr d, mpfr_rnd_t rnd)
+ {
+ mpfr_t ref, res, ab, cd;
+ int inex_ref, inex_res;
+diff -Naurd mpfr-4.1.0-a/tests/tfmod.c mpfr-4.1.0-b/tests/tfmod.c
+--- mpfr-4.1.0-a/tests/tfmod.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tfmod.c 2021-02-11 12:48:27.350242965 +0000
+@@ -62,8 +62,8 @@
+ }
+
+ static void
+-test_failed (mpfr_t erem, mpfr_t grem, int eret, int gret, mpfr_t x, mpfr_t y,
+- mpfr_rnd_t rnd)
++test_failed (mpfr_ptr erem, mpfr_ptr grem, int eret, int gret,
++ mpfr_ptr x, mpfr_ptr y, mpfr_rnd_t rnd)
+ {
+ printf ("error: mpfr_fmod (r, x, y, rnd)\n x = ");
+ mpfr_out_str (stdout, 10, 0, x, MPFR_RNDD);
+@@ -83,7 +83,7 @@
+ }
+
+ static void
+-check (mpfr_t r0, mpfr_t x, mpfr_t y, mpfr_rnd_t rnd)
++check (mpfr_ptr r0, mpfr_ptr x, mpfr_ptr y, mpfr_rnd_t rnd)
+ {
+ int inex0, inex1;
+ mpfr_t r1;
+diff -Naurd mpfr-4.1.0-a/tests/tfprintf.c mpfr-4.1.0-b/tests/tfprintf.c
+--- mpfr-4.1.0-a/tests/tfprintf.c 2020-06-01 10:39:52.000000000 +0000
++++ mpfr-4.1.0-b/tests/tfprintf.c 2021-02-11 12:48:27.350242965 +0000
+@@ -65,7 +65,7 @@
+ const int prec_max_printf = 5000;
+
+ static void
+-check (FILE *fout, const char *fmt, mpfr_t x)
++check (FILE *fout, const char *fmt, mpfr_ptr x)
+ {
+ if (mpfr_fprintf (fout, fmt, x) == -1)
+ {
+diff -Naurd mpfr-4.1.0-a/tests/tgamma.c mpfr-4.1.0-b/tests/tgamma.c
+--- mpfr-4.1.0-a/tests/tgamma.c 2020-06-01 00:15:37.000000000 +0000
++++ mpfr-4.1.0-b/tests/tgamma.c 2021-02-11 12:48:27.350242965 +0000
+@@ -890,7 +890,7 @@
+ computing with a working precision p2. Assume that x is not an
+ integer <= 2. */
+ static void
+-exp_lgamma (mpfr_t x, mpfr_prec_t p1, mpfr_prec_t p2)
++exp_lgamma (mpfr_ptr x, mpfr_prec_t p1, mpfr_prec_t p2)
+ {
+ mpfr_t yd, yu, zd, zu;
+ int inexd, inexu, sign;
+diff -Naurd mpfr-4.1.0-a/tests/tnrandom_chisq.c mpfr-4.1.0-b/tests/tnrandom_chisq.c
+--- mpfr-4.1.0-a/tests/tnrandom_chisq.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tnrandom_chisq.c 2021-02-11 12:48:27.350242965 +0000
+@@ -26,7 +26,7 @@
+ * for the normal distribution. We only take differences of this function so
+ * the offset doesn't matter; here Phi(0) = 0. */
+ static void
+-normal_cumulative (mpfr_t z, mpfr_t x, mpfr_rnd_t rnd)
++normal_cumulative (mpfr_ptr z, mpfr_ptr x, mpfr_rnd_t rnd)
+ {
+ mpfr_sqrt_ui (z, 2, rnd);
+ mpfr_div (z, x, z, rnd);
+@@ -44,7 +44,7 @@
+ * TAOCP, Vol 2, 3.3.1, Table 1. It more accurate than the similar formula,
+ * DLMF 8.11.10. */
+ static void
+-chisq_prob (mpfr_t q, long nu, mpfr_t chisqp)
++chisq_prob (mpfr_ptr q, long nu, mpfr_ptr chisqp)
+ {
+ mpfr_t t;
+ mpfr_rnd_t rnd;
+@@ -166,7 +166,7 @@
+ * this function. low precision means prec = 2, 3, or 4. High values of
+ * precision will result in integer overflow. */
+ static long
+-sequential (mpfr_t x)
++sequential (mpfr_ptr x)
+ {
+ long expt, prec;
+
+diff -Naurd mpfr-4.1.0-a/tests/tprintf.c mpfr-4.1.0-b/tests/tprintf.c
+--- mpfr-4.1.0-a/tests/tprintf.c 2020-06-01 10:39:52.000000000 +0000
++++ mpfr-4.1.0-b/tests/tprintf.c 2021-02-11 12:48:27.350242965 +0000
+@@ -74,7 +74,7 @@
+ int stdout_redirect;
+
+ static void
+-check (const char *fmt, mpfr_t x)
++check (const char *fmt, mpfr_ptr x)
+ {
+ if (mpfr_printf (fmt, x) == -1)
+ {
+diff -Naurd mpfr-4.1.0-a/tests/trint.c mpfr-4.1.0-b/tests/trint.c
+--- mpfr-4.1.0-a/tests/trint.c 2020-02-12 13:04:50.000000000 +0000
++++ mpfr-4.1.0-b/tests/trint.c 2021-02-11 12:48:27.350242965 +0000
+@@ -367,7 +367,7 @@
+ #endif
+
+ static void
+-err (const char *str, mp_size_t s, mpfr_t x, mpfr_t y, mpfr_prec_t p,
++err (const char *str, mp_size_t s, mpfr_ptr x, mpfr_ptr y, mpfr_prec_t p,
+ mpfr_rnd_t r, int trint, int inexact)
+ {
+ printf ("Error: %s\ns = %u, p = %u, r = %s, trint = %d, inexact = %d\nx = ",
+diff -Naurd mpfr-4.1.0-a/tests/tsinh_cosh.c mpfr-4.1.0-b/tests/tsinh_cosh.c
+--- mpfr-4.1.0-a/tests/tsinh_cosh.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tsinh_cosh.c 2021-02-11 12:48:27.350242965 +0000
+@@ -23,7 +23,7 @@
+ #include "mpfr-test.h"
+
+ static void
+-failed (mpfr_t x, mpfr_t esh, mpfr_t gsh, mpfr_t ech, mpfr_t gch)
++failed (mpfr_ptr x, mpfr_ptr esh, mpfr_ptr gsh, mpfr_ptr ech, mpfr_ptr gch)
+ {
+ printf ("error : mpfr_sinh_cosh (x) x = ");
+ mpfr_out_str (stdout, 10, 0, x, MPFR_RNDD);
+@@ -43,7 +43,7 @@
+
+ /* check against sinh, cosh */
+ static void
+-check (mpfr_t x, mpfr_rnd_t rnd)
++check (mpfr_ptr x, mpfr_rnd_t rnd)
+ {
+ mpfr_t s, c, sx, cx;
+ int isc, is, ic;
+diff -Naurd mpfr-4.1.0-a/tests/tsqr.c mpfr-4.1.0-b/tests/tsqr.c
+--- mpfr-4.1.0-a/tests/tsqr.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tsqr.c 2021-02-11 12:48:27.350242965 +0000
+@@ -33,7 +33,7 @@
+
+ static void
+ error1 (mpfr_rnd_t rnd, mpfr_prec_t prec,
+- mpfr_t in, mpfr_t outmul, mpfr_t outsqr)
++ mpfr_t in, mpfr_ptr outmul, mpfr_ptr outsqr)
+ {
+ printf("ERROR: for %s and prec=%lu\nINPUT=", mpfr_print_rnd_mode(rnd),
+ (unsigned long) prec);
+@@ -44,7 +44,7 @@
+ }
+
+ static void
+-error2 (mpfr_rnd_t rnd, mpfr_prec_t prec, mpfr_t in, mpfr_t out,
++error2 (mpfr_rnd_t rnd, mpfr_prec_t prec, mpfr_ptr in, mpfr_ptr out,
+ int inexactmul, int inexactsqr)
+ {
+ printf("ERROR: for %s and prec=%lu\nINPUT=", mpfr_print_rnd_mode(rnd),
+diff -Naurd mpfr-4.1.0-a/tests/tsum.c mpfr-4.1.0-b/tests/tsum.c
+--- mpfr-4.1.0-a/tests/tsum.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tsum.c 2021-02-11 12:48:27.350242965 +0000
+@@ -59,7 +59,7 @@
+ }
+
+ static void
+-get_exact_sum (mpfr_t sum, mpfr_t *tab, int n)
++get_exact_sum (mpfr_ptr sum, mpfr_t *tab, int n)
+ {
+ int i;
+
+@@ -1198,7 +1198,7 @@
+ }
+
+ static int
+-mpfr_sum_naive (mpfr_t s, mpfr_t *x, int n, mpfr_rnd_t rnd)
++mpfr_sum_naive (mpfr_ptr s, mpfr_t *x, int n, mpfr_rnd_t rnd)
+ {
+ int ret, i;
+ switch (n)
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-02-11 12:50:22.384987438 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-02-11 12:50:22.424987002 +0000
+@@ -0,0 +1 @@
++digamma-hugemem
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-02-11 12:48:27.370242746 +0000
++++ mpfr-4.1.0-b/VERSION 2021-02-11 12:50:22.424987002 +0000
+@@ -1 +1 @@
+-4.1.0-p4
++4.1.0-p5
+diff -Naurd mpfr-4.1.0-a/src/digamma.c mpfr-4.1.0-b/src/digamma.c
+--- mpfr-4.1.0-a/src/digamma.c 2020-06-18 17:17:18.000000000 +0000
++++ mpfr-4.1.0-b/src/digamma.c 2021-02-11 12:50:22.412987133 +0000
+@@ -214,19 +214,27 @@
+ (("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec(x), mpfr_log_prec, x, rnd_mode),
+ ("y[%Pu]=%.*Rg inexact=%d", mpfr_get_prec(y), mpfr_log_prec, y, inex));
+
+- /* compute a precision q such that x+1 is exact */
+- if (MPFR_PREC(x) < MPFR_GET_EXP(x))
+- q = MPFR_EXP(x);
+- else
+- q = MPFR_PREC(x) + 1;
+-
+- /* for very large x, use |digamma(x) - log(x)| < 1/x < 2^(1-EXP(x)) */
+- if (MPFR_PREC(y) + 10 < MPFR_EXP(x))
++ /* For very large x, use |digamma(x) - log(x)| < 1/x < 2^(1-EXP(x)).
++ However, for a fixed value of GUARD, MPFR_CAN_ROUND() might fail
++ with probability 1/2^GUARD, in which case the default code will
++ fail since it requires x+1 to be exact, thus a huge precision if
++ x is huge. There are two workarounds:
++ * either perform a Ziv's loop, by increasing GUARD at each step.
++ However, this might fail if x is moderately large, in which case
++ more terms of the asymptotic expansion would be needed.
++ * implement a full asymptotic expansion (with Ziv's loop). */
++#define GUARD 30
++ if (MPFR_PREC(y) + GUARD < MPFR_EXP(x))
+ {
+ /* this ensures EXP(x) >= 3, thus x >= 4, thus log(x) > 1 */
+- mpfr_init2 (t, MPFR_PREC(y) + 10);
+- mpfr_log (t, x, MPFR_RNDZ);
+- if (MPFR_CAN_ROUND (t, MPFR_PREC(y) + 10, MPFR_PREC(y), rnd_mode))
++ mpfr_init2 (t, MPFR_PREC(y) + GUARD);
++ mpfr_log (t, x, MPFR_RNDN);
++ /* |t - digamma(x)| <= 1/2*ulp(t) + |digamma(x) - log(x)|
++ <= 1/2*ulp(t) + 2^(1-EXP(x))
++ <= 1/2*ulp(t) + 2^(-PREC(y)-GUARD)
++ <= ulp(t)
++ since |t| >= 1 thus ulp(t) >= 2^(1-PREC(y)-GUARD) */
++ if (MPFR_CAN_ROUND (t, MPFR_PREC(y) + GUARD, MPFR_PREC(y), rnd_mode))
+ {
+ inex = mpfr_set (y, t, rnd_mode);
+ mpfr_clear (t);
+@@ -235,6 +243,21 @@
+ mpfr_clear (t);
+ }
+
++ /* compute a precision q such that x+1 is exact */
++ if (MPFR_PREC(x) < MPFR_GET_EXP(x))
++ {
++ /* The goal of the first assertion is to let the compiler ignore
++ the second one when MPFR_EMAX_MAX <= MPFR_PREC_MAX. */
++ MPFR_ASSERTD (MPFR_EXP(x) <= MPFR_EMAX_MAX);
++ MPFR_ASSERTN (MPFR_EXP(x) <= MPFR_PREC_MAX);
++ q = MPFR_EXP(x);
++ }
++ else
++ q = MPFR_PREC(x) + 1;
++
++ /* FIXME: q can be much too large, e.g. equal to the maximum exponent! */
++ MPFR_LOG_MSG (("q=%Pu\n", q));
++
+ mpfr_init2 (x_plus_j, q);
+
+ mpfr_init2 (t, p);
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-02-11 12:48:27.366242791 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-02-11 12:50:22.424987002 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p4"
++#define MPFR_VERSION_STRING "4.1.0-p5"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-02-11 12:48:27.370242746 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-02-11 12:50:22.424987002 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p4";
++ return "4.1.0-p5";
+ }
+diff -Naurd mpfr-4.1.0-a/tests/tdigamma.c mpfr-4.1.0-b/tests/tdigamma.c
+--- mpfr-4.1.0-a/tests/tdigamma.c 2020-06-18 17:17:18.000000000 +0000
++++ mpfr-4.1.0-b/tests/tdigamma.c 2021-02-11 12:50:22.412987133 +0000
+@@ -49,12 +49,54 @@
+ mpfr_clear (y);
+ }
+
++/* With some GMP_CHECK_RANDOMIZE values, test_generic triggers an error
++ tests_addsize(): too much memory (576460752303432776 bytes)
++ Each time on prec = 200, n = 3, xprec = 140.
++ The following test is a more general testcase.
++*/
++static void
++bug20210206 (void)
++{
++#define NPREC 4
++ mpfr_t x, y[NPREC], z;
++ mpfr_exp_t emin, emax;
++ int i, precx, precy[NPREC] = { 200, 400, 520, 1416 };
++
++ emin = mpfr_get_emin ();
++ emax = mpfr_get_emax ();
++ set_emin (MPFR_EMIN_MIN);
++ set_emax (MPFR_EMAX_MAX);
++
++ for (i = 0; i < NPREC; i++)
++ mpfr_init2 (y[i], precy[i]);
++ mpfr_init2 (z, precy[0]);
++
++ for (precx = MPFR_PREC_MIN; precx < 150; precx++)
++ {
++ mpfr_init2 (x, precx);
++ mpfr_setmax (x, __gmpfr_emax);
++ for (i = 0; i < NPREC; i++)
++ mpfr_digamma (y[i], x, MPFR_RNDA);
++ mpfr_set (z, y[1], MPFR_RNDA);
++ MPFR_ASSERTN (mpfr_equal_p (y[0], z));
++ mpfr_clear (x);
++ }
++
++ for (i = 0; i < NPREC; i++)
++ mpfr_clear (y[i]);
++ mpfr_clear (z);
++
++ set_emin (emin);
++ set_emax (emax);
++}
++
+ int
+ main (int argc, char *argv[])
+ {
+ tests_start_mpfr ();
+
+ special ();
++ bug20210206 ();
+
+ test_generic (MPFR_PREC_MIN, 200, 20);
+
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-02-11 12:52:52.519350662 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-02-11 12:52:52.563350183 +0000
+@@ -0,0 +1 @@
++digamma-interm-zero
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-02-11 12:50:22.424987002 +0000
++++ mpfr-4.1.0-b/VERSION 2021-02-11 12:52:52.563350183 +0000
+@@ -1 +1 @@
+-4.1.0-p5
++4.1.0-p6
+diff -Naurd mpfr-4.1.0-a/src/digamma.c mpfr-4.1.0-b/src/digamma.c
+--- mpfr-4.1.0-a/src/digamma.c 2021-02-11 12:50:22.412987133 +0000
++++ mpfr-4.1.0-b/src/digamma.c 2021-02-11 12:52:52.547350357 +0000
+@@ -296,21 +296,26 @@
+ errt = mpfr_digamma_approx (t, x_plus_j);
+ expt = MPFR_GET_EXP (t);
+ mpfr_sub (t, t, u, MPFR_RNDN);
+- if (MPFR_GET_EXP (t) < expt)
+- errt += expt - MPFR_EXP(t);
+- /* Warning: if u is zero (which happens when x_plus_j >= min at the
+- beginning of the while loop above), EXP(u) is not defined.
+- In this case we have no error from u. */
+- if (MPFR_NOTZERO(u) && MPFR_GET_EXP (t) < MPFR_GET_EXP (u))
+- erru += MPFR_EXP(u) - MPFR_EXP(t);
+- if (errt > erru)
+- errt = errt + 1;
+- else if (errt == erru)
+- errt = errt + 2;
+- else
+- errt = erru + 1;
+- if (MPFR_CAN_ROUND (t, p - errt, MPFR_PREC(y), rnd_mode))
+- break;
++ /* Warning! t may be zero (more likely in small precision). Note
++ that in this case, this is an exact zero, not an underflow. */
++ if (MPFR_NOTZERO(t))
++ {
++ if (MPFR_GET_EXP (t) < expt)
++ errt += expt - MPFR_EXP(t);
++ /* Warning: if u is zero (which happens when x_plus_j >= min at the
++ beginning of the while loop above), EXP(u) is not defined.
++ In this case we have no error from u. */
++ if (MPFR_NOTZERO(u) && MPFR_GET_EXP (t) < MPFR_GET_EXP (u))
++ erru += MPFR_EXP(u) - MPFR_EXP(t);
++ if (errt > erru)
++ errt = errt + 1;
++ else if (errt == erru)
++ errt = errt + 2;
++ else
++ errt = erru + 1;
++ if (MPFR_CAN_ROUND (t, p - errt, MPFR_PREC(y), rnd_mode))
++ break;
++ }
+ MPFR_ZIV_NEXT (loop, p);
+ mpfr_set_prec (t, p);
+ mpfr_set_prec (u, p);
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-02-11 12:50:22.424987002 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-02-11 12:52:52.559350226 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p5"
++#define MPFR_VERSION_STRING "4.1.0-p6"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-02-11 12:50:22.424987002 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-02-11 12:52:52.559350226 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p5";
++ return "4.1.0-p6";
+ }
+diff -Naurd mpfr-4.1.0-a/tests/tdigamma.c mpfr-4.1.0-b/tests/tdigamma.c
+--- mpfr-4.1.0-a/tests/tdigamma.c 2021-02-11 12:50:22.412987133 +0000
++++ mpfr-4.1.0-b/tests/tdigamma.c 2021-02-11 12:52:52.547350357 +0000
+@@ -90,6 +90,26 @@
+ set_emax (emax);
+ }
+
++/* another test that fails with GMP_CHECK_RANDOMIZE=1612741376857003
++ on revision 14398 */
++static void
++bug20210208 (void)
++{
++ mpfr_t x, y;
++ int inex;
++
++ mpfr_init2 (x, 73);
++ mpfr_init2 (y, 1);
++ mpfr_set_str (x, "1.4613470547060071827450", 10, MPFR_RNDN);
++ mpfr_clear_flags ();
++ inex = mpfr_digamma (y, x, MPFR_RNDU);
++ MPFR_ASSERTN (mpfr_cmp_si_2exp (y, -1, -12) == 0);
++ MPFR_ASSERTN (inex > 0);
++ MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_INEXACT);
++ mpfr_clear (x);
++ mpfr_clear (y);
++}
++
+ int
+ main (int argc, char *argv[])
+ {
+@@ -97,6 +117,7 @@
+
+ special ();
+ bug20210206 ();
++ bug20210208 ();
+
+ test_generic (MPFR_PREC_MIN, 200, 20);
+
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-02-11 12:53:38.382850990 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-02-11 12:53:38.426850512 +0000
+@@ -0,0 +1 @@
++jn-interm-zero
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-02-11 12:52:52.563350183 +0000
++++ mpfr-4.1.0-b/VERSION 2021-02-11 12:53:38.426850512 +0000
+@@ -1 +1 @@
+-4.1.0-p6
++4.1.0-p7
+diff -Naurd mpfr-4.1.0-a/src/jyn_asympt.c mpfr-4.1.0-b/src/jyn_asympt.c
+--- mpfr-4.1.0-a/src/jyn_asympt.c 2020-07-10 10:33:32.000000000 +0000
++++ mpfr-4.1.0-b/src/jyn_asympt.c 2021-02-11 12:53:38.410850685 +0000
+@@ -69,6 +69,8 @@
+ MPFR_ZIV_INIT (loop, w);
+ for (;;)
+ {
++ int ok = 1;
++
+ mpfr_set_prec (c, w);
+ mpfr_init2 (s, w);
+ mpfr_init2 (P, w);
+@@ -92,6 +94,13 @@
+ /* now s approximates sin(z)+cos(z), and c approximates sin(z)-cos(z),
+ with total absolute error bounded by 2^(1-w). */
+
++ /* if s or c is zero, MPFR_GET_EXP will fail below */
++ if (MPFR_IS_ZERO(s) || MPFR_IS_ZERO(c))
++ {
++ ok = 0;
++ goto clear;
++ }
++
+ /* precompute 1/(8|z|) */
+ mpfr_si_div (iz, MPFR_IS_POS(z) ? 1 : -1, z, MPFR_RNDN); /* err <= 1 */
+ mpfr_div_2ui (iz, iz, 3, MPFR_RNDN);
+@@ -257,6 +266,9 @@
+ err = (err >= err2) ? err + 1 : err2 + 1;
+ /* the absolute error on c is bounded by 2^(err - w) */
+
++ err -= MPFR_GET_EXP (c);
++
++ clear:
+ mpfr_clear (s);
+ mpfr_clear (P);
+ mpfr_clear (Q);
+@@ -266,8 +278,7 @@
+ mpfr_clear (err_s);
+ mpfr_clear (err_u);
+
+- err -= MPFR_GET_EXP (c);
+- if (MPFR_LIKELY (MPFR_CAN_ROUND (c, w - err, MPFR_PREC(res), r)))
++ if (ok && MPFR_LIKELY (MPFR_CAN_ROUND (c, w - err, MPFR_PREC(res), r)))
+ break;
+ if (diverge != 0)
+ {
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-02-11 12:52:52.559350226 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-02-11 12:53:38.422850555 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p6"
++#define MPFR_VERSION_STRING "4.1.0-p7"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-02-11 12:52:52.559350226 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-02-11 12:53:38.426850512 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p6";
++ return "4.1.0-p7";
+ }
+diff -Naurd mpfr-4.1.0-a/tests/tj0.c mpfr-4.1.0-b/tests/tj0.c
+--- mpfr-4.1.0-a/tests/tj0.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tj0.c 2021-02-11 12:53:38.410850685 +0000
+@@ -27,6 +27,25 @@
+ #define REDUCE_EMAX 262143 /* otherwise arg. reduction is too expensive */
+ #include "tgeneric.c"
+
++/* bug found in revision 14399 with GMP_CHECK_RANDOMIZE=1612721106588971 */
++static void
++bug20210208 (void)
++{
++ mpfr_t x, y;
++ int inex;
++
++ mpfr_init2 (x, 79);
++ mpfr_init2 (y, 1);
++ mpfr_set_str (x, "2.552495117262005805960565e+02", 10, MPFR_RNDN);
++ mpfr_clear_flags ();
++ inex = mpfr_j0 (y, x, MPFR_RNDZ);
++ MPFR_ASSERTN (mpfr_cmp_si_2exp (y, -1, -5) == 0);
++ MPFR_ASSERTN (inex > 0);
++ MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_INEXACT);
++ mpfr_clear (x);
++ mpfr_clear (y);
++}
++
+ int
+ main (int argc, char *argv[])
+ {
+@@ -35,6 +54,8 @@
+
+ tests_start_mpfr ();
+
++ bug20210208 ();
++
+ mpfr_init (x);
+ mpfr_init (y);
+
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-02-17 17:22:34.594973310 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-02-17 17:22:34.702972090 +0000
+@@ -0,0 +1 @@
++digamma-interm-zero2
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-02-11 12:53:38.426850512 +0000
++++ mpfr-4.1.0-b/VERSION 2021-02-17 17:22:34.702972090 +0000
+@@ -1 +1 @@
+-4.1.0-p7
++4.1.0-p8
+diff -Naurd mpfr-4.1.0-a/src/digamma.c mpfr-4.1.0-b/src/digamma.c
+--- mpfr-4.1.0-a/src/digamma.c 2021-02-11 12:52:52.547350357 +0000
++++ mpfr-4.1.0-b/src/digamma.c 2021-02-17 17:22:34.690972226 +0000
+@@ -173,16 +173,19 @@
+ mpfr_digamma (v, u, MPFR_RNDN); /* error <= 1/2 ulp */
+ expv = MPFR_GET_EXP (v);
+ mpfr_sub (v, v, t, MPFR_RNDN);
+- if (MPFR_GET_EXP (v) < MPFR_GET_EXP (t))
+- e1 += MPFR_EXP(t) - MPFR_EXP(v); /* scale error for t wrt new v */
+- /* now take into account the 1/2 ulp error for v */
+- if (expv - MPFR_EXP(v) - 1 > e1)
+- e1 = expv - MPFR_EXP(v) - 1;
+- else
+- e1 ++;
+- e1 ++; /* rounding error for mpfr_sub */
+- if (MPFR_CAN_ROUND (v, p - e1, MPFR_PREC(y), rnd_mode))
+- break;
++ if (MPFR_NOTZERO(v))
++ {
++ if (MPFR_GET_EXP (v) < MPFR_GET_EXP (t))
++ e1 += MPFR_EXP(t) - MPFR_EXP(v); /* scale error for t wrt new v */
++ /* now take into account the 1/2 ulp error for v */
++ if (expv - MPFR_EXP(v) - 1 > e1)
++ e1 = expv - MPFR_EXP(v) - 1;
++ else
++ e1 ++;
++ e1 ++; /* rounding error for mpfr_sub */
++ if (MPFR_CAN_ROUND (v, p - e1, MPFR_PREC(y), rnd_mode))
++ break;
++ }
+ MPFR_ZIV_NEXT (loop, p);
+ mpfr_set_prec (t, p);
+ mpfr_set_prec (v, p);
+@@ -416,10 +419,8 @@
+ }
+ }
+
+- if (MPFR_IS_NEG(x))
+- inex = mpfr_digamma_reflection (y, x, rnd_mode);
+ /* if x < 1/2 we use the reflection formula */
+- else if (MPFR_EXP(x) < 0)
++ if (MPFR_IS_NEG(x) || MPFR_EXP(x) < 0)
+ inex = mpfr_digamma_reflection (y, x, rnd_mode);
+ else
+ inex = mpfr_digamma_positive (y, x, rnd_mode);
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-02-11 12:53:38.422850555 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-02-17 17:22:34.702972090 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p7"
++#define MPFR_VERSION_STRING "4.1.0-p8"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-02-11 12:53:38.426850512 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-02-17 17:22:34.702972090 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p7";
++ return "4.1.0-p8";
+ }
+diff -Naurd mpfr-4.1.0-a/tests/tdigamma.c mpfr-4.1.0-b/tests/tdigamma.c
+--- mpfr-4.1.0-a/tests/tdigamma.c 2021-02-11 12:52:52.547350357 +0000
++++ mpfr-4.1.0-b/tests/tdigamma.c 2021-02-17 17:22:34.690972226 +0000
+@@ -110,6 +110,26 @@
+ mpfr_clear (y);
+ }
+
++/* another test that fails with GMP_CHECK_RANDOMIZE=1613197421465830
++ on revision 14429 */
++static void
++bug20210215 (void)
++{
++ mpfr_t x, y;
++ int inex;
++
++ mpfr_init2 (x, 510);
++ mpfr_init2 (y, 4);
++ mpfr_set_str (x, "-8.2923051438433494998166335341807999322052669984208422481227138906096000469898717007386115912802685588348601663465077353194268894939972221117314512518182580e+35", 10, MPFR_RNDN);
++ mpfr_clear_flags ();
++ inex = mpfr_digamma (y, x, MPFR_RNDU);
++ MPFR_ASSERTN (mpfr_cmp_ui0 (y, 88) == 0);
++ MPFR_ASSERTN (inex > 0);
++ MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_INEXACT);
++ mpfr_clear (x);
++ mpfr_clear (y);
++}
++
+ int
+ main (int argc, char *argv[])
+ {
+@@ -118,6 +138,7 @@
+ special ();
+ bug20210206 ();
+ bug20210208 ();
++ bug20210215 ();
+
+ test_generic (MPFR_PREC_MIN, 200, 20);
+
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-02-17 17:25:46.396981483 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-02-17 17:25:46.440981068 +0000
+@@ -0,0 +1 @@
++jyn_asympt-interm-zero
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-02-17 17:22:34.702972090 +0000
++++ mpfr-4.1.0-b/VERSION 2021-02-17 17:25:46.440981068 +0000
+@@ -1 +1 @@
+-4.1.0-p8
++4.1.0-p9
+diff -Naurd mpfr-4.1.0-a/src/jyn_asympt.c mpfr-4.1.0-b/src/jyn_asympt.c
+--- mpfr-4.1.0-a/src/jyn_asympt.c 2021-02-11 12:53:38.410850685 +0000
++++ mpfr-4.1.0-b/src/jyn_asympt.c 2021-02-17 17:25:46.424981219 +0000
+@@ -69,7 +69,7 @@
+ MPFR_ZIV_INIT (loop, w);
+ for (;;)
+ {
+- int ok = 1;
++ int ok = 0;
+
+ mpfr_set_prec (c, w);
+ mpfr_init2 (s, w);
+@@ -96,10 +96,7 @@
+
+ /* if s or c is zero, MPFR_GET_EXP will fail below */
+ if (MPFR_IS_ZERO(s) || MPFR_IS_ZERO(c))
+- {
+- ok = 0;
+- goto clear;
+- }
++ goto clear; /* with ok=0 */
+
+ /* precompute 1/(8|z|) */
+ mpfr_si_div (iz, MPFR_IS_POS(z) ? 1 : -1, z, MPFR_RNDN); /* err <= 1 */
+@@ -227,6 +224,9 @@
+ mpfr_sub (s, c, s, MPFR_RNDN);
+ #endif
+ }
++ if (MPFR_IS_ZERO(s))
++ goto clear; /* with ok=0 */
++ ok = 1;
+ if ((n & 2) != 0)
+ mpfr_neg (s, s, MPFR_RNDN);
+ if (MPFR_GET_EXP (s) > err)
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-02-17 17:22:34.702972090 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-02-17 17:25:46.436981105 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p8"
++#define MPFR_VERSION_STRING "4.1.0-p9"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-02-17 17:22:34.702972090 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-02-17 17:25:46.440981068 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p8";
++ return "4.1.0-p9";
+ }
+diff -Naurd mpfr-4.1.0-a/tests/mpfr-test.h mpfr-4.1.0-b/tests/mpfr-test.h
+--- mpfr-4.1.0-a/tests/mpfr-test.h 2020-06-29 13:57:32.000000000 +0000
++++ mpfr-4.1.0-b/tests/mpfr-test.h 2021-02-17 17:25:46.424981219 +0000
+@@ -191,6 +191,8 @@
+
+ #define mpfr_cmp0(x,y) (MPFR_ASSERTN (!MPFR_IS_NAN (x) && !MPFR_IS_NAN (y)), mpfr_cmp (x,y))
+ #define mpfr_cmp_ui0(x,i) (MPFR_ASSERTN (!MPFR_IS_NAN (x)), mpfr_cmp_ui (x,i))
++#define mpfr_cmp_si_2exp0(x,i,e) (MPFR_ASSERTN (!MPFR_IS_NAN (x)), \
++ mpfr_cmp_si_2exp (x,i,e))
+
+ /* define CHECK_EXTERNAL if you want to check mpfr against another library
+ with correct rounding. You'll probably have to modify mpfr_print_raw()
+diff -Naurd mpfr-4.1.0-a/tests/tj1.c mpfr-4.1.0-b/tests/tj1.c
+--- mpfr-4.1.0-a/tests/tj1.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tj1.c 2021-02-17 17:25:46.424981219 +0000
+@@ -55,14 +55,14 @@
+ /* since |x| is just above 2^e, |j1(x)| is just above 2^(e-1),
+ thus y should be 2^(e-1) and the inexact flag should be
+ of opposite sign of x */
+- MPFR_ASSERTN(mpfr_cmp_si_2exp (y, sign, e - 1) == 0);
++ MPFR_ASSERTN(mpfr_cmp_si_2exp0 (y, sign, e - 1) == 0);
+ MPFR_ASSERTN(VSIGN (inex) * sign < 0);
+ }
+ else
+ {
+ /* here |y| should be 0.5*2^emin and the inexact flag should
+ have the sign of x */
+- MPFR_ASSERTN(mpfr_cmp_si_2exp (y, sign, e) == 0);
++ MPFR_ASSERTN(mpfr_cmp_si_2exp0 (y, sign, e) == 0);
+ MPFR_ASSERTN(VSIGN (inex) * sign > 0);
+ }
+ }
+@@ -72,6 +72,26 @@
+ mpfr_clear (y);
+ }
+
++/* a test that fails with GMP_CHECK_RANDOMIZE=1613146232984428
++ on revision 14429 */
++static void
++bug20210215 (void)
++{
++ mpfr_t x, y;
++ int inex;
++
++ mpfr_init2 (x, 221);
++ mpfr_init2 (y, 1);
++ mpfr_set_str (x, "1.6484611511696130037307738844228498447763863563070374544054791168614e+01", 10, MPFR_RNDN);
++ mpfr_clear_flags ();
++ inex = mpfr_j1 (y, x, MPFR_RNDZ);
++ MPFR_ASSERTN (mpfr_cmp_si_2exp0 (y, -1, -9) == 0);
++ MPFR_ASSERTN (inex > 0);
++ MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_INEXACT);
++ mpfr_clear (x);
++ mpfr_clear (y);
++}
++
+ int
+ main (int argc, char *argv[])
+ {
+@@ -79,6 +99,8 @@
+
+ tests_start_mpfr ();
+
++ bug20210215 ();
++
+ test_small ();
+
+ mpfr_init (x);
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-03-09 13:55:43.183158946 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-03-09 13:55:43.223158508 +0000
+@@ -0,0 +1 @@
++macros
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-02-17 17:25:46.440981068 +0000
++++ mpfr-4.1.0-b/VERSION 2021-03-09 13:55:43.223158508 +0000
+@@ -1 +1 @@
+-4.1.0-p9
++4.1.0-p10
+diff -Naurd mpfr-4.1.0-a/doc/mpfr.info mpfr-4.1.0-b/doc/mpfr.info
+--- mpfr-4.1.0-a/doc/mpfr.info 2020-07-10 11:59:13.000000000 +0000
++++ mpfr-4.1.0-b/doc/mpfr.info 2021-03-09 13:55:51.167071327 +0000
+@@ -3217,7 +3217,11 @@
+
+ Each function in this interface is also implemented as a macro for
+ efficiency reasons: for example ‘mpfr_custom_init (s, p)’ uses the
+-macro, while ‘(mpfr_custom_init) (s, p)’ uses the function.
++macro, while ‘(mpfr_custom_init) (s, p)’ uses the function. Note that
++the macro may evaluate arguments multiple times (or none). Moreover,
++macros implementing functions with the ‘void’ return type may not be
++used in contexts where an expression is expected, e.g., inside
++‘for(...)’ or before a comma operator.
+
+ Note 1: MPFR functions may still initialize temporary floating-point
+ numbers using ‘mpfr_init’ and similar functions. See Custom Allocation
+@@ -4579,13 +4583,13 @@
+ (line 115)
+ * mpfr_csch: Transcendental Functions.
+ (line 180)
+-* mpfr_custom_get_exp: Custom Interface. (line 76)
+-* mpfr_custom_get_kind: Custom Interface. (line 66)
+-* mpfr_custom_get_significand: Custom Interface. (line 71)
+-* mpfr_custom_get_size: Custom Interface. (line 37)
+-* mpfr_custom_init: Custom Interface. (line 41)
+-* mpfr_custom_init_set: Custom Interface. (line 48)
+-* mpfr_custom_move: Custom Interface. (line 85)
++* mpfr_custom_get_exp: Custom Interface. (line 80)
++* mpfr_custom_get_kind: Custom Interface. (line 70)
++* mpfr_custom_get_significand: Custom Interface. (line 75)
++* mpfr_custom_get_size: Custom Interface. (line 41)
++* mpfr_custom_init: Custom Interface. (line 45)
++* mpfr_custom_init_set: Custom Interface. (line 52)
++* mpfr_custom_move: Custom Interface. (line 89)
+ * MPFR_DECL_INIT: Initialization Functions.
+ (line 77)
+ * mpfr_digamma: Transcendental Functions.
+@@ -5165,19 +5169,19 @@
+ Node: Memory Handling Functions155904
+ Node: Compatibility with MPF157792
+ Node: Custom Interface160961
+-Node: Internals165592
+-Node: API Compatibility167136
+-Node: Type and Macro Changes169084
+-Node: Added Functions172267
+-Node: Changed Functions177074
+-Node: Removed Functions184433
+-Node: Other Changes185163
+-Node: MPFR and the IEEE 754 Standard186864
+-Node: Contributors189481
+-Node: References192620
+-Node: GNU Free Documentation License194501
+-Node: Concept Index217095
+-Node: Function and Type Index223168
++Node: Internals165852
++Node: API Compatibility167396
++Node: Type and Macro Changes169344
++Node: Added Functions172527
++Node: Changed Functions177334
++Node: Removed Functions184693
++Node: Other Changes185423
++Node: MPFR and the IEEE 754 Standard187124
++Node: Contributors189741
++Node: References192880
++Node: GNU Free Documentation License194761
++Node: Concept Index217355
++Node: Function and Type Index223428
+
+ End Tag Table
+
+diff -Naurd mpfr-4.1.0-a/doc/mpfr.texi mpfr-4.1.0-b/doc/mpfr.texi
+--- mpfr-4.1.0-a/doc/mpfr.texi 2020-07-10 11:52:33.000000000 +0000
++++ mpfr-4.1.0-b/doc/mpfr.texi 2021-03-09 13:55:43.211158639 +0000
+@@ -3817,6 +3817,12 @@
+ Each function in this interface is also implemented as a macro for
+ efficiency reasons: for example @code{mpfr_custom_init (s, p)}
+ uses the macro, while @code{(mpfr_custom_init) (s, p)} uses the function.
++Note that the macro may evaluate arguments multiple times (or none).
++Moreover, macros implementing functions with the @code{void} return type
++may not be used in contexts where an expression is expected, e.g., inside
++@code{for(...)} or before a comma operator.
++@c These limitations with macros cannot be avoided in a C90 compatible way.
++@c In the future, inline functions could be used.
+
+ Note 1: MPFR functions may still initialize temporary floating-point numbers
+ using @code{mpfr_init} and similar functions. See Custom Allocation (GNU MP)@.
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-02-17 17:25:46.436981105 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-03-09 13:55:43.223158508 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p9"
++#define MPFR_VERSION_STRING "4.1.0-p10"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+@@ -833,23 +833,39 @@
+ even if it produces faster and smaller code. */
+ #ifndef MPFR_USE_NO_MACRO
+
+-/* Inlining these functions is both faster and smaller */
+-#define mpfr_nan_p(_x) ((_x)->_mpfr_exp == __MPFR_EXP_NAN)
+-#define mpfr_inf_p(_x) ((_x)->_mpfr_exp == __MPFR_EXP_INF)
+-#define mpfr_zero_p(_x) ((_x)->_mpfr_exp == __MPFR_EXP_ZERO)
+-#define mpfr_regular_p(_x) ((_x)->_mpfr_exp > __MPFR_EXP_INF)
++/* In the implementation of these macros, we need to make sure that the
++ arguments are evaluated one time exactly and that type conversion is
++ done as it would be with a function. Tests should be added to ensure
++ that.
++ Note that the macros for the custom interface are not concerned; the
++ MPFR manual has been clarified. */
++
++/* Prevent x from being used as an lvalue.
++ Thanks to Wojtek Lerch and Tim Rentsch for the idea. */
++#define MPFR_VALUE_OF(x) (0 ? (x) : (x))
++
++/* The following macro converts the argument to mpfr_srcptr, as in type
++ conversion for function parameters. But it will detect disallowed
++ implicit conversions, e.g. when the argument has an integer type. */
++#define MPFR_SRCPTR(x) ((mpfr_srcptr) (0 ? (x) : (mpfr_srcptr) (x)))
++#define MPFR_GET_SIGN(_x) MPFR_VALUE_OF(MPFR_SIGN(MPFR_SRCPTR(_x)))
++
++#define mpfr_nan_p(_x) (MPFR_SRCPTR(_x)->_mpfr_exp == __MPFR_EXP_NAN)
++#define mpfr_inf_p(_x) (MPFR_SRCPTR(_x)->_mpfr_exp == __MPFR_EXP_INF)
++#define mpfr_zero_p(_x) (MPFR_SRCPTR(_x)->_mpfr_exp == __MPFR_EXP_ZERO)
++#define mpfr_regular_p(_x) (MPFR_SRCPTR(_x)->_mpfr_exp > __MPFR_EXP_INF)
++
++/* mpfr_sgn is documented as a macro, thus the following code is fine.
++ But it would be safer to regard it as a function in some future
++ MPFR version. */
+ #define mpfr_sgn(_x) \
+ ((_x)->_mpfr_exp < __MPFR_EXP_INF ? \
+ (mpfr_nan_p (_x) ? mpfr_set_erangeflag () : (mpfr_void) 0), 0 : \
+ MPFR_SIGN (_x))
+
+-/* Prevent them from using as lvalues */
+-#define MPFR_VALUE_OF(x) (0 ? (x) : (x))
+-#define mpfr_get_prec(_x) MPFR_VALUE_OF((_x)->_mpfr_prec)
+-#define mpfr_get_exp(_x) MPFR_VALUE_OF((_x)->_mpfr_exp)
+-/* Note 1: If need be, the MPFR_VALUE_OF can be used for other expressions
+- (of any type). Thanks to Wojtek Lerch and Tim Rentsch for the idea.
+- Note 2: Defining mpfr_get_exp() as a macro has the effect to disable
++#define mpfr_get_prec(_x) MPFR_VALUE_OF(MPFR_SRCPTR(_x)->_mpfr_prec)
++#define mpfr_get_exp(_x) MPFR_VALUE_OF(MPFR_SRCPTR(_x)->_mpfr_exp)
++/* Note: Defining mpfr_get_exp() as a macro has the effect to disable
+ the check that the argument is a pure FP number (done in the function);
+ this increases the risk of undetected error and makes debugging more
+ complex. Is it really worth in practice? (Potential FIXME) */
+@@ -861,11 +877,17 @@
+
+ #define mpfr_cmp_ui(b,i) mpfr_cmp_ui_2exp((b),(i),0)
+ #define mpfr_cmp_si(b,i) mpfr_cmp_si_2exp((b),(i),0)
+-#define mpfr_set(a,b,r) mpfr_set4(a,b,r,MPFR_SIGN(b))
++#if __GNUC__ > 2 || __GNUC_MINOR__ >= 95
++#define mpfr_set(a,b,r) \
++ __extension__ ({ \
++ mpfr_srcptr _p = (b); \
++ mpfr_set4(a,_p,r,MPFR_SIGN(_p)); \
++ })
++#endif
+ #define mpfr_abs(a,b,r) mpfr_set4(a,b,r,1)
+-#define mpfr_copysign(a,b,c,r) mpfr_set4(a,b,r,MPFR_SIGN(c))
++#define mpfr_copysign(a,b,c,r) mpfr_set4(a,b,r,MPFR_GET_SIGN(c))
+ #define mpfr_setsign(a,b,s,r) mpfr_set4(a,b,r,(s) ? -1 : 1)
+-#define mpfr_signbit(x) (MPFR_SIGN(x) < 0)
++#define mpfr_signbit(x) (MPFR_GET_SIGN(x) < 0)
+ #define mpfr_cmp(b, c) mpfr_cmp3(b, c, 1)
+ #define mpfr_mul_2exp(y,x,n,r) mpfr_mul_2ui((y),(x),(n),(r))
+ #define mpfr_div_2exp(y,x,n,r) mpfr_div_2ui((y),(x),(n),(r))
+diff -Naurd mpfr-4.1.0-a/src/ubf.c mpfr-4.1.0-b/src/ubf.c
+--- mpfr-4.1.0-a/src/ubf.c 2020-02-12 01:38:57.000000000 +0000
++++ mpfr-4.1.0-b/src/ubf.c 2021-03-09 13:55:43.211158639 +0000
+@@ -78,7 +78,7 @@
+ mpfr_get_prec (b), mpfr_log_prec, b,
+ mpfr_get_prec (c), mpfr_log_prec, c),
+ ("a[%Pu]=%.*Rg",
+- mpfr_get_prec (a), mpfr_log_prec, a));
++ mpfr_get_prec ((mpfr_ptr) a), mpfr_log_prec, a));
+
+ MPFR_ASSERTD ((mpfr_ptr) a != b);
+ MPFR_ASSERTD ((mpfr_ptr) a != c);
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-02-17 17:25:46.440981068 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-03-09 13:55:43.223158508 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p9";
++ return "4.1.0-p10";
+ }
+diff -Naurd mpfr-4.1.0-a/tests/mpfr-test.h mpfr-4.1.0-b/tests/mpfr-test.h
+--- mpfr-4.1.0-a/tests/mpfr-test.h 2021-02-17 17:25:46.424981219 +0000
++++ mpfr-4.1.0-b/tests/mpfr-test.h 2021-03-09 13:55:43.211158639 +0000
+@@ -92,6 +92,32 @@
+ #define STRINGIZE(S) #S
+ #define MAKE_STR(S) STRINGIZE(S)
+
++/* In C (but not C++), mpfr_ptr and mpfr_srcptr arguments can be provided
++ in a different pointer type, such as void *. For functions implemented
++ as macros, the type conversion for the function parameters will not be
++ done by the compiler, which means potential bugs in these implementations
++ if we forget to take these unusual cases into account. So we need to test
++ such arguments, in order to make sure that the arguments are converted to
++ the expected type when needed.
++
++ However, at least when the function is not implemented as a macro (which
++ is the case when MPFR_USE_NO_MACRO is defined), such tests with void *
++ arguments are not valid in C++; therefore, we will not do the cast to
++ void * if the __cplusplus macro is defined. And with GCC compilers (and
++ compatible), we will ignore the -Wc++-compat option around these tests.
++
++ Note: in the future, inline functions could be used instead of macros,
++ and such tests would become useless (except to detect compiler bugs).
++*/
++#if defined (__cplusplus)
++#define VOIDP_CAST(X) (X)
++#else
++#define VOIDP_CAST(X) ((void *) (X))
++#if defined (__GNUC__)
++#define IGNORE_CPP_COMPAT
++#endif
++#endif
++
+ #if defined (__cplusplus)
+ extern "C" {
+ #endif
+diff -Naurd mpfr-4.1.0-a/tests/tcopysign.c mpfr-4.1.0-b/tests/tcopysign.c
+--- mpfr-4.1.0-a/tests/tcopysign.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tcopysign.c 2021-03-09 13:55:43.211158639 +0000
+@@ -26,26 +26,72 @@
+ copysign_variant (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y,
+ mpfr_rnd_t rnd_mode, int k)
+ {
++ mpfr_srcptr p;
++ int a = 0, b = 0, c = 0;
++
++ /* invalid sign, to test that the sign is always correctly set */
++ MPFR_SIGN (z) = 0;
++
++ if (k >= 8)
++ {
++ MPFR_ASSERTN (MPFR_PREC (z) >= MPFR_PREC (x));
++ mpfr_set (z, x, MPFR_RNDN);
++ p = z;
++ k -= 8;
++ }
++ else
++ p = x;
++
+ mpfr_clear_flags ();
+ switch (k)
+ {
+ case 0:
+- mpfr_copysign (z, x, y, MPFR_RNDN);
++ mpfr_copysign (z, p, y, rnd_mode);
+ return;
+ case 1:
+- (mpfr_copysign) (z, x, y, MPFR_RNDN);
++ (mpfr_copysign) (z, p, y, rnd_mode);
+ return;
+ case 2:
+- mpfr_setsign (z, x, mpfr_signbit (y), MPFR_RNDN);
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wc++-compat"
++#endif
++ mpfr_copysign ((a++, VOIDP_CAST(z)),
++ (b++, VOIDP_CAST(p)),
++ (c++, VOIDP_CAST(y)), rnd_mode);
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic pop
++#endif
++ MPFR_ASSERTN (a == 1);
++ MPFR_ASSERTN (b == 1);
++ MPFR_ASSERTN (c == 1);
+ return;
+ case 3:
+- mpfr_setsign (z, x, (mpfr_signbit) (y), MPFR_RNDN);
++ mpfr_setsign (z, p, mpfr_signbit (y), rnd_mode);
+ return;
+ case 4:
+- (mpfr_setsign) (z, x, mpfr_signbit (y), MPFR_RNDN);
++ mpfr_setsign (z, p, (mpfr_signbit) (y), rnd_mode);
+ return;
+ case 5:
+- (mpfr_setsign) (z, x, (mpfr_signbit) (y), MPFR_RNDN);
++ (mpfr_setsign) (z, p, mpfr_signbit (y), rnd_mode);
++ return;
++ case 6:
++ (mpfr_setsign) (z, p, (mpfr_signbit) (y), rnd_mode);
++ return;
++ case 7:
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wc++-compat"
++#endif
++ mpfr_setsign ((a++, VOIDP_CAST(z)),
++ (b++, VOIDP_CAST(p)),
++ mpfr_signbit ((c++, VOIDP_CAST(y))), rnd_mode);
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic pop
++#endif
++ MPFR_ASSERTN (a == 1);
++ MPFR_ASSERTN (b == 1);
++ MPFR_ASSERTN (c == 1);
+ return;
+ }
+ }
+@@ -64,7 +110,7 @@
+
+ for (i = 0; i <= 1; i++)
+ for (j = 0; j <= 1; j++)
+- for (k = 0; k <= 5; k++)
++ for (k = 0; k < 16; k++)
+ {
+ mpfr_set_nan (x);
+ i ? MPFR_SET_NEG (x) : MPFR_SET_POS (x);
+diff -Naurd mpfr-4.1.0-a/tests/texceptions.c mpfr-4.1.0-b/tests/texceptions.c
+--- mpfr-4.1.0-a/tests/texceptions.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/texceptions.c 2021-03-09 13:55:43.211158639 +0000
+@@ -103,10 +103,26 @@
+ check_get_prec (void)
+ {
+ mpfr_t x;
++ int i = 0;
+
+ mpfr_init2 (x, 17);
+- if (mpfr_get_prec (x) != 17 || (mpfr_get_prec)(x) != 17)
++
++ if (mpfr_get_prec (x) != 17 || (mpfr_get_prec) (x) != 17)
+ PRINT_ERROR ("mpfr_get_prec");
++
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wc++-compat"
++#endif
++
++ if (mpfr_get_prec ((i++, VOIDP_CAST(x))) != 17)
++ PRINT_ERROR ("mpfr_get_prec (2)");
++
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic pop
++#endif
++
++ MPFR_ASSERTN (i == 1);
+ mpfr_clear (x);
+ }
+
+diff -Naurd mpfr-4.1.0-a/tests/tisnan.c mpfr-4.1.0-b/tests/tisnan.c
+--- mpfr-4.1.0-a/tests/tisnan.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tisnan.c 2021-03-09 13:55:43.211158639 +0000
+@@ -27,180 +27,235 @@
+ main (void)
+ {
+ mpfr_t x;
++ int i = 0, j = 0;
++
++ /* We need to check that when the function is implemented by a macro,
++ it behaves correctly. */
++#define ARG (i++, VOIDP_CAST(x))
++#define CHECK MPFR_ASSERTN (i == ++j)
+
+ tests_start_mpfr ();
+
+ mpfr_init (x);
+
++#if 0
++ /* The following should yield a compilation error when the functions
++ are implemented as macros. Change 0 to 1 above in order to test. */
++ (void) (mpfr_nan_p (1L));
++ (void) (mpfr_inf_p (1L));
++ (void) (mpfr_number_p (1L));
++ (void) (mpfr_zero_p (1L));
++ (void) (mpfr_regular_p (1L));
++#endif
++
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wc++-compat"
++#endif
++
+ /* check +infinity gives non-zero for mpfr_inf_p only */
+ mpfr_set_ui (x, 1L, MPFR_RNDZ);
+ mpfr_div_ui (x, x, 0L, MPFR_RNDZ);
+- if (mpfr_nan_p (x) || (mpfr_nan_p) (x) )
++ if (mpfr_nan_p (x) || (mpfr_nan_p) (x) || mpfr_nan_p (ARG))
+ {
+ printf ("Error: mpfr_nan_p(+Inf) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_inf_p (x) == 0)
++ CHECK;
++ if (!mpfr_inf_p (x) || !(mpfr_inf_p) (x) || !mpfr_inf_p (ARG))
+ {
+ printf ("Error: mpfr_inf_p(+Inf) gives zero\n");
+ exit (1);
+ }
+- if (mpfr_number_p (x) || (mpfr_number_p) (x) )
++ CHECK;
++ if (mpfr_number_p (x) || (mpfr_number_p) (x) || mpfr_number_p (ARG))
+ {
+ printf ("Error: mpfr_number_p(+Inf) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_zero_p (x) || (mpfr_zero_p) (x) )
++ CHECK;
++ if (mpfr_zero_p (x) || (mpfr_zero_p) (x) || mpfr_zero_p (ARG))
+ {
+ printf ("Error: mpfr_zero_p(+Inf) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_regular_p (x) || (mpfr_regular_p) (x) )
++ CHECK;
++ if (mpfr_regular_p (x) || (mpfr_regular_p) (x) || mpfr_regular_p (ARG))
+ {
+ printf ("Error: mpfr_regular_p(+Inf) gives non-zero\n");
+ exit (1);
+ }
++ CHECK;
+
+ /* same for -Inf */
+ mpfr_neg (x, x, MPFR_RNDN);
+- if (mpfr_nan_p (x) || (mpfr_nan_p(x)))
++ if (mpfr_nan_p (x) || (mpfr_nan_p) (x) || mpfr_nan_p (ARG))
+ {
+ printf ("Error: mpfr_nan_p(-Inf) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_inf_p (x) == 0)
++ CHECK;
++ if (!mpfr_inf_p (x) || !(mpfr_inf_p) (x) || !mpfr_inf_p (ARG))
+ {
+ printf ("Error: mpfr_inf_p(-Inf) gives zero\n");
+ exit (1);
+ }
+- if (mpfr_number_p (x) || (mpfr_number_p)(x) )
++ CHECK;
++ if (mpfr_number_p (x) || (mpfr_number_p) (x) || mpfr_number_p (ARG))
+ {
+ printf ("Error: mpfr_number_p(-Inf) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_zero_p (x) || (mpfr_zero_p)(x) )
++ CHECK;
++ if (mpfr_zero_p (x) || (mpfr_zero_p) (x) || mpfr_zero_p (ARG))
+ {
+ printf ("Error: mpfr_zero_p(-Inf) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_regular_p (x) || (mpfr_regular_p) (x) )
++ CHECK;
++ if (mpfr_regular_p (x) || (mpfr_regular_p) (x) || mpfr_regular_p (ARG))
+ {
+ printf ("Error: mpfr_regular_p(-Inf) gives non-zero\n");
+ exit (1);
+ }
++ CHECK;
+
+ /* same for NaN */
+ mpfr_sub (x, x, x, MPFR_RNDN);
+- if (mpfr_nan_p (x) == 0)
++ if (!mpfr_nan_p (x) || !(mpfr_nan_p) (x) || !mpfr_nan_p (ARG))
+ {
+ printf ("Error: mpfr_nan_p(NaN) gives zero\n");
+ exit (1);
+ }
+- if (mpfr_inf_p (x) || (mpfr_inf_p)(x) )
++ CHECK;
++ if (mpfr_inf_p (x) || (mpfr_inf_p) (x) || mpfr_inf_p (ARG))
+ {
+ printf ("Error: mpfr_inf_p(NaN) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_number_p (x) || (mpfr_number_p) (x) )
++ CHECK;
++ if (mpfr_number_p (x) || (mpfr_number_p) (x) || mpfr_number_p (ARG))
+ {
+ printf ("Error: mpfr_number_p(NaN) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_zero_p (x) || (mpfr_zero_p)(x) )
++ CHECK;
++ if (mpfr_zero_p (x) || (mpfr_zero_p) (x) || mpfr_zero_p (ARG))
+ {
+ printf ("Error: mpfr_number_p(NaN) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_regular_p (x) || (mpfr_regular_p) (x) )
++ CHECK;
++ if (mpfr_regular_p (x) || (mpfr_regular_p) (x) || mpfr_regular_p (ARG))
+ {
+ printf ("Error: mpfr_regular_p(NaN) gives non-zero\n");
+ exit (1);
+ }
++ CHECK;
+
+ /* same for a regular number */
+ mpfr_set_ui (x, 1, MPFR_RNDN);
+- if (mpfr_nan_p (x) || (mpfr_nan_p)(x))
++ if (mpfr_nan_p (x) || (mpfr_nan_p) (x) || mpfr_nan_p (ARG))
+ {
+ printf ("Error: mpfr_nan_p(1) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_inf_p (x) || (mpfr_inf_p)(x) )
++ CHECK;
++ if (mpfr_inf_p (x) || (mpfr_inf_p) (x) || mpfr_inf_p (ARG))
+ {
+ printf ("Error: mpfr_inf_p(1) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_number_p (x) == 0)
++ CHECK;
++ if (!mpfr_number_p (x) || !(mpfr_number_p) (x) || !mpfr_number_p (ARG))
+ {
+ printf ("Error: mpfr_number_p(1) gives zero\n");
+ exit (1);
+ }
+- if (mpfr_zero_p (x) || (mpfr_zero_p) (x) )
++ CHECK;
++ if (mpfr_zero_p (x) || (mpfr_zero_p) (x) || mpfr_zero_p (ARG))
+ {
+ printf ("Error: mpfr_zero_p(1) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_regular_p (x) == 0 || (mpfr_regular_p) (x) == 0)
++ CHECK;
++ if (!mpfr_regular_p (x) || !(mpfr_regular_p) (x) || !mpfr_regular_p (ARG))
+ {
+ printf ("Error: mpfr_regular_p(1) gives zero\n");
+ exit (1);
+ }
++ CHECK;
+
+ /* Same for +0 */
+ mpfr_set_ui (x, 0, MPFR_RNDN);
+- if (mpfr_nan_p (x) || (mpfr_nan_p)(x))
++ if (mpfr_nan_p (x) || (mpfr_nan_p) (x) || mpfr_nan_p (ARG))
+ {
+ printf ("Error: mpfr_nan_p(+0) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_inf_p (x) || (mpfr_inf_p)(x) )
++ CHECK;
++ if (mpfr_inf_p (x) || (mpfr_inf_p) (x) || mpfr_inf_p (ARG))
+ {
+ printf ("Error: mpfr_inf_p(+0) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_number_p (x) == 0)
++ CHECK;
++ if (!mpfr_number_p (x) || !(mpfr_number_p) (x) || !mpfr_number_p (ARG))
+ {
+ printf ("Error: mpfr_number_p(+0) gives zero\n");
+ exit (1);
+ }
+- if (mpfr_zero_p (x) == 0 )
++ CHECK;
++ if (!mpfr_zero_p (x) || !(mpfr_zero_p) (x) || !mpfr_zero_p (ARG))
+ {
+ printf ("Error: mpfr_zero_p(+0) gives zero\n");
+ exit (1);
+ }
+- if (mpfr_regular_p (x) || (mpfr_regular_p) (x) )
++ CHECK;
++ if (mpfr_regular_p (x) || (mpfr_regular_p) (x) || mpfr_regular_p (ARG))
+ {
+ printf ("Error: mpfr_regular_p(+0) gives non-zero\n");
+ exit (1);
+ }
++ CHECK;
+
+ /* Same for -0 */
+ mpfr_set_ui (x, 0, MPFR_RNDN);
+ mpfr_neg (x, x, MPFR_RNDN);
+- if (mpfr_nan_p (x) || (mpfr_nan_p)(x))
++ if (mpfr_nan_p (x) || (mpfr_nan_p) (x) || mpfr_nan_p (ARG))
+ {
+ printf ("Error: mpfr_nan_p(-0) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_inf_p (x) || (mpfr_inf_p)(x) )
++ CHECK;
++ if (mpfr_inf_p (x) || (mpfr_inf_p) (x) || mpfr_inf_p (ARG))
+ {
+ printf ("Error: mpfr_inf_p(-0) gives non-zero\n");
+ exit (1);
+ }
+- if (mpfr_number_p (x) == 0)
++ CHECK;
++ if (!mpfr_number_p (x) || !(mpfr_number_p) (x) || !mpfr_number_p (ARG))
+ {
+ printf ("Error: mpfr_number_p(-0) gives zero\n");
+ exit (1);
+ }
+- if (mpfr_zero_p (x) == 0 )
++ CHECK;
++ if (!mpfr_zero_p (x) || !(mpfr_zero_p) (x) || !mpfr_zero_p (ARG))
+ {
+ printf ("Error: mpfr_zero_p(-0) gives zero\n");
+ exit (1);
+ }
+- if (mpfr_regular_p (x) || (mpfr_regular_p) (x) )
++ CHECK;
++ if (mpfr_regular_p (x) || (mpfr_regular_p) (x) || mpfr_regular_p (ARG))
+ {
+ printf ("Error: mpfr_regular_p(-0) gives non-zero\n");
+ exit (1);
+ }
++ CHECK;
++
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic pop
++#endif
+
+ mpfr_clear (x);
+
+diff -Naurd mpfr-4.1.0-a/tests/tset.c mpfr-4.1.0-b/tests/tset.c
+--- mpfr-4.1.0-a/tests/tset.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tset.c 2021-03-09 13:55:43.207158683 +0000
+@@ -207,7 +207,7 @@
+ static void
+ check_ternary_value (void)
+ {
+- int p, q, rnd;
++ int k, p, q, rnd;
+ int inexact, cmp;
+ mpfr_t x, y;
+
+@@ -226,28 +226,45 @@
+ {
+ if (rnd == MPFR_RNDF) /* the test below makes no sense */
+ continue;
+- inexact = mpfr_set (y, x, (mpfr_rnd_t) rnd);
+- cmp = mpfr_cmp (y, x);
+- if (((inexact == 0) && (cmp != 0)) ||
+- ((inexact > 0) && (cmp <= 0)) ||
+- ((inexact < 0) && (cmp >= 0)))
+- {
+- printf ("Wrong ternary value in mpfr_set for %s: expected"
+- " %d, got %d\n",
+- mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), cmp,
+- inexact);
+- exit (1);
+- }
+- /* Test mpfr_set function too */
+- inexact = (mpfr_set) (y, x, (mpfr_rnd_t) rnd);
+- cmp = mpfr_cmp (y, x);
+- if (((inexact == 0) && (cmp != 0)) ||
+- ((inexact > 0) && (cmp <= 0)) ||
+- ((inexact < 0) && (cmp >= 0)))
++ for (k = 0; k < 3; k++)
+ {
+- printf ("Wrong ternary value in mpfr_set(2): expected %d,"
+- " got %d\n", cmp, inexact);
+- exit (1);
++ int a = 0, b = 0, c = 0;
++
++ switch (k)
++ {
++ case 0:
++ inexact = mpfr_set (y, x, (mpfr_rnd_t) rnd);
++ break;
++ case 1:
++ inexact = (mpfr_set) (y, x, (mpfr_rnd_t) rnd);
++ break;
++ case 2:
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wc++-compat"
++#endif
++ inexact = mpfr_set ((a++, VOIDP_CAST(y)),
++ (b++, VOIDP_CAST(x)),
++ (c++, (mpfr_rnd_t) rnd));
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic pop
++#endif
++ MPFR_ASSERTN (a == 1);
++ MPFR_ASSERTN (b == 1);
++ MPFR_ASSERTN (c == 1);
++ break;
++ }
++ cmp = mpfr_cmp (y, x);
++ if (((inexact == 0) && (cmp != 0)) ||
++ ((inexact > 0) && (cmp <= 0)) ||
++ ((inexact < 0) && (cmp >= 0)))
++ {
++ printf ("Wrong ternary value in mpfr_set for %s (%d):"
++ " expected %d, got %d\n",
++ mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
++ k, cmp, inexact);
++ exit (1);
++ }
+ }
+ }
+ }
+diff -Naurd mpfr-4.1.0-a/tests/tset_exp.c mpfr-4.1.0-b/tests/tset_exp.c
+--- mpfr-4.1.0-a/tests/tset_exp.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tset_exp.c 2021-03-09 13:55:43.211158639 +0000
+@@ -28,6 +28,7 @@
+ mpfr_t x;
+ int ret;
+ mpfr_exp_t emin, emax, e;
++ int i = 0;
+
+ tests_start_mpfr ();
+
+@@ -63,6 +64,17 @@
+ e = (mpfr_get_exp) (x);
+ MPFR_ASSERTN (e == emin);
+
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wc++-compat"
++#endif
++ e = mpfr_get_exp ((i++, VOIDP_CAST(x)));
++#ifdef IGNORE_CPP_COMPAT
++#pragma GCC diagnostic pop
++#endif
++ MPFR_ASSERTN (e == emin);
++ MPFR_ASSERTN (i == 1);
++
+ ret = mpfr_set_exp (x, -1);
+ MPFR_ASSERTN (ret == 0 && mpfr_cmp_ui_2exp (x, 1, -2) == 0);
+
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-03-09 13:58:00.889650773 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-03-09 13:58:00.937650249 +0000
+@@ -0,0 +1 @@
++tset_sij
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-03-09 13:55:43.223158508 +0000
++++ mpfr-4.1.0-b/VERSION 2021-03-09 13:58:00.937650249 +0000
+@@ -1 +1 @@
+-4.1.0-p10
++4.1.0-p11
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-03-09 13:55:43.223158508 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-03-09 13:58:00.933650293 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p10"
++#define MPFR_VERSION_STRING "4.1.0-p11"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-03-09 13:55:43.223158508 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-03-09 13:58:00.933650293 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p10";
++ return "4.1.0-p11";
+ }
+diff -Naurd mpfr-4.1.0-a/tests/tset_si.c mpfr-4.1.0-b/tests/tset_si.c
+--- mpfr-4.1.0-a/tests/tset_si.c 2020-03-26 11:51:33.000000000 +0000
++++ mpfr-4.1.0-b/tests/tset_si.c 2021-03-09 13:58:00.917650467 +0000
+@@ -127,27 +127,29 @@
+ power of 2 is exact, unless underflow/overflow occurs.
+ The tests on the exponent below avoid integer overflows
+ (ep[i] may take extreme values). */
+- e = mpfr_get_exp (x1);
+ mpfr_clear_flags ();
+- if (j != 0 && ep[i] < __gmpfr_emin - e) /* underflow */
++ if (j == 0)
++ goto zero;
++ e = MPFR_GET_EXP (x1);
++ if (ep[i] < __gmpfr_emin - e) /* underflow */
+ {
+ mpfr_rnd_t r =
+ (rnd == MPFR_RNDN &&
+- (ep[i] < __gmpfr_emin - mpfr_get_exp (y) - 1 ||
++ (ep[i] < __gmpfr_emin - MPFR_GET_EXP (y) - 1 ||
+ IS_POW2 (sign * j))) ?
+ MPFR_RNDZ : (mpfr_rnd_t) rnd;
+ inex1 = mpfr_underflow (x1, r, sign);
+ flags1 = __gmpfr_flags;
+ }
+- else if (j != 0 && ep[i] > __gmpfr_emax - e) /* overflow */
++ else if (ep[i] > __gmpfr_emax - e) /* overflow */
+ {
+ inex1 = mpfr_overflow (x1, (mpfr_rnd_t) rnd, sign);
+ flags1 = __gmpfr_flags;
+ }
+ else
+ {
+- if (j != 0)
+- mpfr_set_exp (x1, ep[i] + e);
++ mpfr_set_exp (x1, ep[i] + e);
++ zero:
+ flags1 = inex1 != 0 ? MPFR_FLAGS_INEXACT : 0;
+ }
+
+diff -Naurd mpfr-4.1.0-a/tests/tset_sj.c mpfr-4.1.0-b/tests/tset_sj.c
+--- mpfr-4.1.0-a/tests/tset_sj.c 2020-06-01 10:39:52.000000000 +0000
++++ mpfr-4.1.0-b/tests/tset_sj.c 2021-03-09 13:58:00.917650467 +0000
+@@ -225,27 +225,29 @@
+ power of 2 is exact, unless underflow/overflow occurs.
+ The tests on the exponent below avoid integer overflows
+ (ep[i] may take extreme values). */
+- e = mpfr_get_exp (x1);
+ mpfr_clear_flags ();
+- if (j != 0 && ep[i] < __gmpfr_emin - e) /* underflow */
++ if (j == 0)
++ goto zero;
++ e = MPFR_GET_EXP (x1);
++ if (ep[i] < __gmpfr_emin - e) /* underflow */
+ {
+ mpfr_rnd_t r =
+ (rnd == MPFR_RNDN &&
+- (ep[i] < __gmpfr_emin - mpfr_get_exp (y) - 1 ||
++ (ep[i] < __gmpfr_emin - MPFR_GET_EXP (y) - 1 ||
+ IS_POW2 (sign * j))) ?
+ MPFR_RNDZ : (mpfr_rnd_t) rnd;
+ inex1 = mpfr_underflow (x1, r, sign);
+ flags1 = __gmpfr_flags;
+ }
+- else if (j != 0 && ep[i] > __gmpfr_emax - e) /* overflow */
++ else if (ep[i] > __gmpfr_emax - e) /* overflow */
+ {
+ inex1 = mpfr_overflow (x1, (mpfr_rnd_t) rnd, sign);
+ flags1 = __gmpfr_flags;
+ }
+ else
+ {
+- if (j != 0)
+- mpfr_set_exp (x1, ep[i] + e);
++ mpfr_set_exp (x1, ep[i] + e);
++ zero:
+ flags1 = inex1 != 0 ? MPFR_FLAGS_INEXACT : 0;
+ }
+ }
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-04-23 09:49:34.648281897 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-04-23 09:49:34.696281616 +0000
+@@ -0,0 +1 @@
++get_str_ndigits
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-03-09 13:58:00.937650249 +0000
++++ mpfr-4.1.0-b/VERSION 2021-04-23 09:49:34.696281616 +0000
+@@ -1 +1 @@
+-4.1.0-p11
++4.1.0-p12
+diff -Naurd mpfr-4.1.0-a/src/get_str.c mpfr-4.1.0-b/src/get_str.c
+--- mpfr-4.1.0-a/src/get_str.c 2020-06-18 17:17:18.000000000 +0000
++++ mpfr-4.1.0-b/src/get_str.c 2021-04-23 09:49:34.680281710 +0000
+@@ -2484,6 +2484,8 @@
+ size_t
+ mpfr_get_str_ndigits (int b, mpfr_prec_t p)
+ {
++ MPFR_SAVE_EXPO_DECL (expo);
++
+ MPFR_ASSERTN (2 <= b && b <= 62);
+
+ /* deal first with power of two bases, since even for those, mpfr_ceil_mul
+@@ -2497,17 +2499,26 @@
+ return 1 + (p + k - 2) / k;
+ }
+
++ MPFR_SAVE_EXPO_MARK (expo);
++
+ /* the value returned by mpfr_ceil_mul is guaranteed to be
+ 1 + ceil(p*log(2)/log(b)) for p < 186564318007 (it returns one more
+ for p=186564318007 and b=7 or 49) */
+ MPFR_STAT_STATIC_ASSERT (MPFR_PREC_BITS >= 64 || MPFR_PREC_BITS <= 32);
++ if
+ #if MPFR_PREC_BITS >= 64
+ /* 64-bit numbers are supported by the C implementation, so that we can
+ use the large constant below. If MPFR_PREC_BITS <= 32, the condition
+ is always satisfied, so that we do not need any test. */
+- if (MPFR_LIKELY (p < 186564318007))
++ (MPFR_LIKELY (p < 186564318007))
++#else
++ (1)
+ #endif
+- return 1 + mpfr_ceil_mul (IS_POW2(b) ? p - 1 : p, b, 1);
++ {
++ size_t ret = 1 + mpfr_ceil_mul (IS_POW2(b) ? p - 1 : p, b, 1);
++ MPFR_SAVE_EXPO_FREE (expo);
++ return ret;
++ }
+
+ /* Now p is large and b is not a power of two. The code below works for any
+ value of p and b, as long as b is not a power of two. Indeed, in such a
+@@ -2541,6 +2552,8 @@
+ mpfr_clear (d);
+ mpfr_clear (u);
+ }
++
++ MPFR_SAVE_EXPO_FREE (expo);
+ return 1 + ret;
+ }
+ }
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-03-09 13:58:00.933650293 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-04-23 09:49:34.692281639 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p11"
++#define MPFR_VERSION_STRING "4.1.0-p12"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-03-09 13:58:00.933650293 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-04-23 09:49:34.696281616 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p11";
++ return "4.1.0-p12";
+ }
+diff -Naurd mpfr-4.1.0-a/tests/tget_str.c mpfr-4.1.0-b/tests/tget_str.c
+--- mpfr-4.1.0-a/tests/tget_str.c 2020-01-08 18:11:13.000000000 +0000
++++ mpfr-4.1.0-b/tests/tget_str.c 2021-04-23 09:49:34.680281710 +0000
+@@ -1311,6 +1311,33 @@
+ mpfr_clear (x);
+ }
+
++static void
++test_ndigits_aux (int b, mpfr_prec_t p, size_t expected_m)
++{
++ size_t m;
++ mpfr_exp_t old_emin, old_emax, e[] = { MPFR_EMIN_MIN, 0, MPFR_EMAX_MAX };
++ mpfr_flags_t flags;
++ int i;
++
++ old_emin = mpfr_get_emin ();
++ old_emax = mpfr_get_emax ();
++
++ i = randlimb () % (numberof (e) + 1);
++ if (i < numberof (e))
++ {
++ set_emin (e[i]);
++ set_emax (e[i]);
++ }
++
++ __gmpfr_flags = flags = randlimb () & MPFR_FLAGS_ALL;
++ m = mpfr_get_str_ndigits (b, p);
++ MPFR_ASSERTN (m == expected_m);
++ MPFR_ASSERTN (__gmpfr_flags == flags);
++
++ set_emin (old_emin);
++ set_emax (old_emax);
++}
++
+ /* test of mpfr_get_str_ndigits */
+ static void
+ test_ndigits (void)
+@@ -1319,61 +1346,61 @@
+
+ /* for b=2, we have 1 + ceil((p-1)*log(2)/log(b)) = p */
+ for (p = MPFR_PREC_MIN; p <= 1024; p++)
+- MPFR_ASSERTN(mpfr_get_str_ndigits (2, p) == p);
++ test_ndigits_aux (2, p, p);
+
+ /* for b=4, we have 1 + ceil((p-1)*log(2)/log(b)) = 1 + ceil((p-1)/2)
+ = 1 + floor(p/2) */
+ for (p = MPFR_PREC_MIN; p <= 1024; p++)
+- MPFR_ASSERTN(mpfr_get_str_ndigits (4, p) == 1 + (p / 2));
++ test_ndigits_aux (4, p, 1 + (p / 2));
+
+ /* for b=8, we have 1 + ceil((p-1)*log(2)/log(b)) = 1 + ceil((p-1)/3)
+ = 1 + floor((p+1)/3) */
+ for (p = MPFR_PREC_MIN; p <= 1024; p++)
+- MPFR_ASSERTN(mpfr_get_str_ndigits (8, p) == 1 + ((p + 1) / 3));
++ test_ndigits_aux (8, p, 1 + ((p + 1) / 3));
+
+ /* for b=16, we have 1 + ceil((p-1)*log(2)/log(b)) = 1 + ceil((p-1)/4)
+ = 1 + floor((p+2)/4) */
+ for (p = MPFR_PREC_MIN; p <= 1024; p++)
+- MPFR_ASSERTN(mpfr_get_str_ndigits (16, p) == 1 + ((p + 2) / 4));
++ test_ndigits_aux (16, p, 1 + ((p + 2) / 4));
+
+ /* for b=32, we have 1 + ceil((p-1)*log(2)/log(b)) = 1 + ceil((p-1)/5)
+ = 1 + floor((p+3)/5) */
+ for (p = MPFR_PREC_MIN; p <= 1024; p++)
+- MPFR_ASSERTN(mpfr_get_str_ndigits (32, p) == 1 + ((p + 3) / 5));
++ test_ndigits_aux (32, p, 1 + ((p + 3) / 5));
+
+ /* error < 1e-3 */
+- MPFR_ASSERTN(mpfr_get_str_ndigits (57, 35) == 8);
++ test_ndigits_aux (57, 35, 8);
+
+ /* error < 1e-4 */
+- MPFR_ASSERTN(mpfr_get_str_ndigits (31, 649) == 133);
++ test_ndigits_aux (31, 649, 133);
+
+ /* error < 1e-5 */
+- MPFR_ASSERTN(mpfr_get_str_ndigits (43, 5041) == 931);
++ test_ndigits_aux (43, 5041, 931);
+
+ /* error < 1e-6 */
+- MPFR_ASSERTN(mpfr_get_str_ndigits (41, 17771) == 3319);
++ test_ndigits_aux (41, 17771, 3319);
+
+ /* 20th convergent of log(2)/log(3) */
+- MPFR_ASSERTN(mpfr_get_str_ndigits (3, 630138897) == 397573381);
++ test_ndigits_aux (3, 630138897, 397573381);
+
+ #if MPFR_PREC_BITS >= 64
+ /* 21st convergent of log(2)/log(3) */
+- MPFR_ASSERTN(mpfr_get_str_ndigits (3, 9809721694) == 6189245292);
++ test_ndigits_aux (3, 9809721694, 6189245292);
+
+ /* 22nd convergent of log(2)/log(3) */
+- MPFR_ASSERTN(mpfr_get_str_ndigits (3, 10439860591) == 6586818672);
++ test_ndigits_aux (3, 10439860591, 6586818672);
+
+ /* 23rd convergent of log(2)/log(3) */
+- MPFR_ASSERTN(mpfr_get_str_ndigits (3, 103768467013) == 65470613322);
++ test_ndigits_aux (3, 103768467013, 65470613322);
+
+ /* 24th convergent of log(2)/log(3) */
+- MPFR_ASSERTN(mpfr_get_str_ndigits (3, 217976794617) == 137528045314);
++ test_ndigits_aux (3, 217976794617, 137528045314);
+
+- MPFR_ASSERTN(mpfr_get_str_ndigits (3, 1193652440098) == 753110839882);
++ test_ndigits_aux (3, 1193652440098, 753110839882);
+
+- MPFR_ASSERTN(mpfr_get_str_ndigits (3, 683381996816440) == 431166034846569);
++ test_ndigits_aux (3, 683381996816440, 431166034846569);
+
+- MPFR_ASSERTN(mpfr_get_str_ndigits (7, 186564318007) == 66455550933);
++ test_ndigits_aux (7, 186564318007, 66455550933);
+ #endif
+ }
+
+diff -Naurd mpfr-4.1.0-a/PATCHES mpfr-4.1.0-b/PATCHES
+--- mpfr-4.1.0-a/PATCHES 2021-05-17 16:09:00.574477185 +0000
++++ mpfr-4.1.0-b/PATCHES 2021-05-17 16:09:00.754476587 +0000
+@@ -0,0 +1 @@
++vasprintf-prec-zero
+diff -Naurd mpfr-4.1.0-a/VERSION mpfr-4.1.0-b/VERSION
+--- mpfr-4.1.0-a/VERSION 2021-04-23 09:49:34.696281616 +0000
++++ mpfr-4.1.0-b/VERSION 2021-05-17 16:09:00.754476587 +0000
+@@ -1 +1 @@
+-4.1.0-p12
++4.1.0-p13
+diff -Naurd mpfr-4.1.0-a/src/mpfr.h mpfr-4.1.0-b/src/mpfr.h
+--- mpfr-4.1.0-a/src/mpfr.h 2021-04-23 09:49:34.692281639 +0000
++++ mpfr-4.1.0-b/src/mpfr.h 2021-05-17 16:09:00.754476587 +0000
+@@ -27,7 +27,7 @@
+ #define MPFR_VERSION_MAJOR 4
+ #define MPFR_VERSION_MINOR 1
+ #define MPFR_VERSION_PATCHLEVEL 0
+-#define MPFR_VERSION_STRING "4.1.0-p12"
++#define MPFR_VERSION_STRING "4.1.0-p13"
+
+ /* User macros:
+ MPFR_USE_FILE: Define it to make MPFR define functions dealing
+diff -Naurd mpfr-4.1.0-a/src/vasprintf.c mpfr-4.1.0-b/src/vasprintf.c
+--- mpfr-4.1.0-a/src/vasprintf.c 2021-02-11 12:48:27.354242922 +0000
++++ mpfr-4.1.0-b/src/vasprintf.c 2021-05-17 16:09:00.598477107 +0000
+@@ -635,7 +635,13 @@
+ static int
+ buffer_cat (struct string_buffer *b, const char *s, size_t len)
+ {
+- MPFR_ASSERTD (len > 0);
++ /* If len == 0, which is possible when outputting an integer 0
++ (either a native one or mpfr_prec_t) with precision field = 0,
++ do nothing. This test is not necessary since the code below is
++ valid for len == 0, but this is safer, just in case. */
++ if (len == 0)
++ return 0;
++
+ MPFR_ASSERTD (len <= strlen (s));
+
+ if (buffer_incr_len (b, len))
+diff -Naurd mpfr-4.1.0-a/src/version.c mpfr-4.1.0-b/src/version.c
+--- mpfr-4.1.0-a/src/version.c 2021-04-23 09:49:34.696281616 +0000
++++ mpfr-4.1.0-b/src/version.c 2021-05-17 16:09:00.754476587 +0000
+@@ -25,5 +25,5 @@
+ const char *
+ mpfr_get_version (void)
+ {
+- return "4.1.0-p12";
++ return "4.1.0-p13";
+ }
+diff -Naurd mpfr-4.1.0-a/tests/tsprintf.c mpfr-4.1.0-b/tests/tsprintf.c
+--- mpfr-4.1.0-a/tests/tsprintf.c 2020-04-08 22:39:35.000000000 +0000
++++ mpfr-4.1.0-b/tests/tsprintf.c 2021-05-17 16:09:00.598477107 +0000
+@@ -193,6 +193,10 @@
+ sprintf (buf, "%d", i);
+ check_vsprintf (buf, "%d", i);
+
++ check_vsprintf ("0", "%d", 0);
++ check_vsprintf ("", "%.d", 0);
++ check_vsprintf ("", "%.0d", 0);
++
+ sprintf (buf, "%e", d);
+ check_vsprintf (buf, "%e", d);
+
+@@ -227,9 +231,6 @@
+ mpfr_prec_t p = 128;
+ mpfr_t x, y, z;
+
+- mpfr_init (z);
+- mpfr_init2 (x, p);
+-
+ /* specifier 'P' for precision */
+ check_vsprintf ("128", "%Pu", p);
+ check_vsprintf ("00128", "%.5Pu", p);
+@@ -247,9 +248,19 @@
+ check_vsprintf ("0200:", "%0#+ -Po:", p);
+ check_vsprintf ("+0000128 :", "%0+ *.*Pd:", -9, 7, p);
+ check_vsprintf ("+12345 :", "%0+ -*.*Pd:", -9, -3, (mpfr_prec_t) 12345);
++ check_vsprintf ("0", "%Pu", (mpfr_prec_t) 0);
+ /* Do not add a test like "%05.1Pd" as MS Windows is buggy: when
+ a precision is given, the '0' flag must be ignored. */
+
++ /* specifier 'P' with precision field 0 */
++ check_vsprintf ("128", "%.Pu", p);
++ check_vsprintf ("128", "%.0Pd", p);
++ /* check_vsprintf ("", "%.Pu", (mpfr_prec_t) 0); */
++ check_vsprintf ("", "%.0Pd", (mpfr_prec_t) 0);
++
++ mpfr_init (z);
++ mpfr_init2 (x, 128);
++
+ /* special numbers */
+ mpfr_set_inf (x, 1);
+ check_sprintf (pinf_str, "%Re", x);
--
2.36.0