summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2018-04-19 15:51:55 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2018-04-19 15:51:55 +0000
commit4ec86410d6774ba9c22dd8dbee3ee7378609f6a3 (patch)
tree8a2fe7eb2186caa8f2c97d551e562143e825a36b
parent46ead58b10497e9e112d1edd6a1f140becd217ee (diff)
downloadmpfr-4ec86410d6774ba9c22dd8dbee3ee7378609f6a3.tar.gz
Fixed an issue with mpfr_get_str: The number 1 of significant digits
output in the string is now fully supported, i.e. * the value 1 can be provided for n (4th argument); * if n = 0, then the number of significant digits in the output string can now be 1, as already implied by the documentation (but the code was increasing it to 2). Changes: * doc/mpfr.texi: updated mpfr_get_str description to accept n = 1. * src/get_str.c: fixed the code as explained above (for n = 0, removed the increase to 2, and removed an MPFR_ASSERTN). * tests/tget_str.c: added tests. (merged changesets from the trunk: r12430 on tests/tget_str.c only; r12432,12434,12440) git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/4.0@12642 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--doc/mpfr.texi7
-rw-r--r--src/get_str.c9
-rw-r--r--tests/tget_str.c36
3 files changed, 43 insertions, 9 deletions
diff --git a/doc/mpfr.texi b/doc/mpfr.texi
index 009087db0..54156445c 100644
--- a/doc/mpfr.texi
+++ b/doc/mpfr.texi
@@ -1655,8 +1655,8 @@ than in MPFR, so that an overflow or underflow is not possible.
@deftypefun {char *} mpfr_get_str (char *@var{str}, mpfr_exp_t *@var{expptr}, int @var{b}, size_t @var{n}, mpfr_t @var{op}, mpfr_rnd_t @var{rnd})
Convert @var{op} to a string of digits in base @var{b}, with rounding in
the direction @var{rnd}, where @var{n} is either zero (see below) or the
-number of significant digits output in the string; in the latter case,
-@var{n} must be greater or equal to 2. The base may vary from 2 to 62;
+number of significant digits output in the string.
+The base may vary from 2 to 62;
otherwise the function does nothing and immediately returns a null pointer.
If the input is NaN, then the returned string is @samp{@@NaN@@} and the
@@ -1699,8 +1699,7 @@ with @var{p} replaced by @var{p}@minus{}1 if @var{b} is a power of 2,
but in some very rare cases, it might be @math{m+1}
(the smallest case for bases up to 62 is when @var{p} equals 186564318007
for bases 7 and 49).
-@c In the source src/get_str.c, this is due to the approximate mpfr_ceil_mul,
-@c but also m = 1 is changed to 2.
+@c In the source src/get_str.c, this is due to the approximate mpfr_ceil_mul.
If @var{str} is a null pointer, space for the significand is allocated using
the allocation function (@pxref{Memory Handling}) and a pointer to the string
diff --git a/src/get_str.c b/src/get_str.c
index 63c50cb00..8494d213d 100644
--- a/src/get_str.c
+++ b/src/get_str.c
@@ -2325,15 +2325,12 @@ mpfr_get_str (char *s, mpfr_exp_t *e, int b, size_t m, mpfr_srcptr x,
*/
m = 1 +
mpfr_ceil_mul (IS_POW2(b) ? MPFR_PREC(x) - 1 : MPFR_PREC(x), b, 1);
- if (m < 2)
- m = 2;
}
MPFR_LOG_MSG (("m=%zu\n", m));
- /* The code below for non-power-of-two bases works for m=1;
- this is important for the internal use of mpfr_get_str. */
- MPFR_ASSERTN (m >= 2 || (!IS_POW2(b) && m >= 1));
+ /* The code below works for m=1, both for power-of-two and non-power-of-two
+ bases; this is important for the internal use of mpfr_get_str. */
/* x is a floating-point number */
@@ -2376,6 +2373,8 @@ mpfr_get_str (char *s, mpfr_exp_t *e, int b, size_t m, mpfr_srcptr x,
/* the first digit will contain only r bits */
prec = (m - 1) * pow2 + r; /* total number of bits */
+ /* if m=1 then 1 <= prec <= pow2, and since prec=1 is now valid in MPFR,
+ the power-of-two code also works for m=1 */
n = MPFR_PREC2LIMBS (prec);
MPFR_TMP_MARK (marker);
diff --git a/tests/tget_str.c b/tests/tget_str.c
index b49d3a013..2ede2c07e 100644
--- a/tests/tget_str.c
+++ b/tests/tget_str.c
@@ -1267,6 +1267,41 @@ check_negative_base (void)
#define ITER 1000
+static void
+coverage (void)
+{
+ mpfr_t x;
+ char s[42];
+ mpfr_exp_t e;
+ int b = 3;
+ size_t m = 40;
+
+ mpfr_init2 (x, 128);
+
+ /* exercise corner case in mpfr_get_str_aux: exact case (e < 0), where r
+ rounds to a power of 2, and f is a multiple of GMP_NUMB_BITS */
+ mpfr_set_ui_2exp (x, 1, 64, MPFR_RNDU);
+ mpfr_nextbelow (x);
+ /* x = 2^64 - 2^(-64) */
+ mpfr_get_str (s, &e, b, m, x, MPFR_RNDU);
+ /* s is the base-3 string for 6148914691236517206 (in base 10) */
+ MPFR_ASSERTN(strcmp (s, "1111222002212212010121102012021021021200") == 0);
+ MPFR_ASSERTN(e == 41);
+
+ /* exercise corner case in mpfr_get_str: input is m=0, then it is changed
+ to m=1 */
+ mpfr_set_prec (x, 1);
+ mpfr_set_ui (x, 1, MPFR_RNDN);
+ mpfr_get_str (s, &e, 2, 0, x, MPFR_RNDN);
+ MPFR_ASSERTN(strcmp (s, "1") == 0);
+ MPFR_ASSERTN(e == 1);
+ mpfr_get_str (s, &e, 2, 1, x, MPFR_RNDN);
+ MPFR_ASSERTN(strcmp (s, "1") == 0);
+ MPFR_ASSERTN(e == 1);
+
+ mpfr_clear (x);
+}
+
int
main (int argc, char *argv[])
{
@@ -1281,6 +1316,7 @@ main (int argc, char *argv[])
tests_start_mpfr ();
+ coverage ();
check_small ();
check_special (2, 2);