summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2003-02-27 10:20:34 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2003-02-27 10:20:34 +0000
commit27af749912c743bc9c81acaf81d2661397b69e3f (patch)
treedf34a8a147e10392ae710fde66f59068d0a21cdc
parent54b77a5f5b256d816e0f0e8d3a2d5c09cd822e3a (diff)
downloadmpfr-27af749912c743bc9c81acaf81d2661397b69e3f.tar.gz
mpfr_set_str now accepts a binary exponent for base 16
(as defined by the ISO C99 standard). git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@2252 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--mpfr.texi10
-rw-r--r--set_str.c18
-rw-r--r--tests/tset_str.c16
3 files changed, 36 insertions, 8 deletions
diff --git a/mpfr.texi b/mpfr.texi
index ba73c9cbd..995cac501 100644
--- a/mpfr.texi
+++ b/mpfr.texi
@@ -1349,10 +1349,12 @@ Return the number of bytes written, or if an error occurred, return 0.
Input a string in base @var{base} from stdio stream @var{stream},
rounded in direction @var{rnd}, and put the
read float in @var{rop}. The string is of the form @samp{M@@N} or, if the
-base is 10 or less, alternatively @samp{MeN} or @samp{MEN}.
-@samp{M} is the mantissa and
-@samp{N} is the exponent. The mantissa is always in the specified base. The
-exponent is read in decimal.
+base is 10 or less, alternatively @samp{MeN} or @samp{MEN}, or, if the base
+is 16, alternatively @samp{MpB} or @samp{MPB}.
+@samp{M} is the mantissa in the specified base, @samp{N} is the exponent
+written in decimal for the specified base, and in base 16, @samp{B} is the
+binary exponent written in decimal (it indicates the power of 2 by which
+the mantissa is to be scaled).
The argument @var{base} may be in the range 2 to 36.
Unlike the corresponding @code{mpz} function, the base will not be determined
diff --git a/set_str.c b/set_str.c
index c177d4017..5ae402693 100644
--- a/set_str.c
+++ b/set_str.c
@@ -79,6 +79,7 @@ mpfr_set_str (mpfr_t x, const char *str, int base, mp_rnd_t rnd)
mp_exp_t pr; /* needed precision requise for str */
mp_exp_t exp_s = 0; /* exponent in base 'base', normalized for a
mantissa 0.xxx...xxx */
+ mp_exp_t binexp = 0; /* binary exponent (for base 16) */
mp_exp_t prec_x; /* working precision for x */
char *str1; /* copy of str, should not be modified */
size_t size_str1; /* number of characters in str1 */
@@ -146,6 +147,17 @@ mpfr_set_str (mpfr_t x, const char *str, int base, mp_rnd_t rnd)
}
break;
}
+ else if (base == 16 && (*str == 'p' || *str == 'P'))
+ {
+ char *endptr[1];
+ binexp = (mp_exp_t) strtol (str + 1, endptr, 10);
+ if (**endptr != '\0')
+ {
+ res = -1; /* invalid input: garbage after exponent */
+ goto end;
+ }
+ break;
+ }
else if (*str == '.')
{
point = 1;
@@ -177,7 +189,7 @@ mpfr_set_str (mpfr_t x, const char *str, int base, mp_rnd_t rnd)
goto sign_and_flags;
}
- /* now we have str = 0.mant_s[0]...mant_s[prec_s-1]*base^exp_s */
+ /* now we have str = 0.mant_s[0]...mant_s[prec_s-1]*base^exp_s*2^binexp */
/* determine the minimal precision for the computation */
prec_x = MPFR_PREC(x) + (mp_exp_t) __gmpfr_ceil_log2 ((double) MPFR_PREC(x));
@@ -239,8 +251,8 @@ mpfr_set_str (mpfr_t x, const char *str, int base, mp_rnd_t rnd)
count_leading_zeros (pow2, (mp_limb_t) base);
pow2 = BITS_PER_MP_LIMB - pow2 - 1; /* base = 2^pow2 */
-
- exp_y = exp_y + pow2 * (exp_s - (mp_exp_t) pr);
+
+ exp_y += pow2 * (exp_s - (mp_exp_t) pr) + binexp;
result = y - n;
}
diff --git a/tests/tset_str.c b/tests/tset_str.c
index e8a31f18e..1eb550908 100644
--- a/tests/tset_str.c
+++ b/tests/tset_str.c
@@ -89,7 +89,7 @@ main (int argc, char *argv[])
mpfr_set_str (y, "4.936a52bc17254@-133", 16, GMP_RNDN);
if (mpfr_cmp (x, y))
{
- fprintf (stderr, "Error in mpfr_set_str (1):\n");
+ fprintf (stderr, "Error in mpfr_set_str (1a):\n");
mpfr_print_binary (x);
putchar ('\n');
mpfr_print_binary (y);
@@ -99,6 +99,20 @@ main (int argc, char *argv[])
exit (1);
}
+ mpfr_set_str_raw (x, "0.111111101101110010111010100110000111011001010100001101E-529");
+ mpfr_set_str (y, "0.fedcba98765434P-529", 16, GMP_RNDN);
+ if (mpfr_cmp (x, y))
+ {
+ fprintf (stderr, "Error in mpfr_set_str (1b):\n");
+ mpfr_print_binary (x);
+ putchar ('\n');
+ mpfr_print_binary (y);
+ putchar ('\n');
+ mpfr_clear (x);
+ mpfr_clear (y);
+ exit (1);
+ }
+
(*__gmp_free_func) (str, nc * sizeof(char));
mpfr_set_prec (x, 53);