summaryrefslogtreecommitdiff
path: root/get_str.c
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2000-02-11 17:18:40 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2000-02-11 17:18:40 +0000
commitaab9ca0a75e9f7663435439c026776aa2cc8fd79 (patch)
tree078baec0ae316133ba64d4efed4bdab5ea35a15b /get_str.c
parentb45da4327ee545cbf3bc4dbeaf7c589af18997d6 (diff)
downloadmpfr-aab9ca0a75e9f7663435439c026776aa2cc8fd79.tar.gz
unsigned char -> mp_rnd_t
SIGN -> MPFR_SIGN git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@472 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'get_str.c')
-rw-r--r--get_str.c53
1 files changed, 42 insertions, 11 deletions
diff --git a/get_str.c b/get_str.c
index e100b300e..15c667dc2 100644
--- a/get_str.c
+++ b/get_str.c
@@ -37,19 +37,19 @@ MA 02111-1307, USA. */
*/
#if __STDC__
char *mpfr_get_str(char *str, mp_exp_t *expptr, int base, size_t n,
- mpfr_srcptr op, unsigned char rnd_mode)
+ mpfr_srcptr op, mp_rnd_t rnd_mode)
#else
char *mpfr_get_str(str, expptr, base, n, op, rnd_mode)
- char *str;
+ char *str;
mp_exp_t *expptr;
int base;
size_t n;
- mpfr_srcptr op;
- unsigned char rnd_mode;
+ mpfr_srcptr op;
+ mp_rnd_t rnd_mode;
#endif
{
double d; long e, q, div, p, err, prec, sh; mpfr_t a, b; mpz_t bz;
- char *str0; unsigned char rnd1; int f, pow2, ok=0, neg;
+ char *str0; mp_rnd_t rnd1; int f, pow2, ok=0, neg, n0=n;
if (base<2 || 36<base) {
fprintf(stderr, "Error: too small or too large base in mpfr_get_str: %d\n",
@@ -57,11 +57,11 @@ char *mpfr_get_str(str, expptr, base, n, op, rnd_mode)
exit(1);
}
- neg = (SIGN(op)<0) ? 1 : 0;
+ neg = (MPFR_SIGN(op)<0) ? 1 : 0;
if (!NOTZERO(op)) {
if (str==NULL) str0=str=(*_mp_allocate_func)(neg + n + 2);
- if (SIGN(op)<0) *str++ = '-';
+ if (MPFR_SIGN(op)<0) *str++ = '-';
for (f=0;f<n;f++) *str++ = '0';
*expptr = 1;
return str0;
@@ -86,11 +86,17 @@ char *mpfr_get_str(str, expptr, base, n, op, rnd_mode)
y*base^(f-n) <= x*2^(e-p) < (x+1)*2^(e-p) <= (y+1)*base^(f-n)
which implies 2^(EXP(op)-PREC(op)) <= base^(f-n)
*/
- n = f + (int) ceil(((double)PREC(op)-e)*log(2.0)/log((double)base));
+ n = f + (int) floor(((double)PREC(op)-e)*log(2.0)/log((double)base));
}
+#ifdef DEBUG
+ printf("f=%d n=%d EXP(op)=%d PREC(op)=%d\n", f, n, e, PREC(op));
+#endif
/* now the first n digits of the mantissa are obtained from
rnd(op*base^(n-f)) */
prec = (long) ceil((double)n*log((double)base)/log(2.0));
+#ifdef DEBUG
+ printf("prec=%d\n", prec);
+#endif
err = 5;
q = prec+err;
/* one has to use at least q bits */
@@ -126,16 +132,26 @@ char *mpfr_get_str(str, expptr, base, n, op, rnd_mode)
mpfr_div(a, b, a, rnd_mode);
}
/* now a is an approximation by default of 1/base^(f-n) */
+#ifdef DEBUG
+ printf("a=%1.20e\n", mpfr_get_d(a));
+#endif
mpfr_mul(b, op, a, rnd_mode);
}
}
if (neg) CHANGE_SIGN(b); /* put b positive */
-
+#ifdef DEBUG
+ printf("p=%d b=%1.20e\n", p, mpfr_get_d(b));
+ printf("q=%d 2*prec+BITS_PER_MP_LIMB=%d\n", q, 2*prec+BITS_PER_MP_LIMB);
+#endif
if (q>2*prec+BITS_PER_MP_LIMB) {
/* happens when just in the middle between two digits */
n--; q-=BITS_PER_MP_LIMB;
if (n==0) {
- fprintf(stderr, "cannot determine leading digit\n"); exit(1);
+ fprintf(stderr, "Error in mpfr_get_str: cannot determine leading digit\n");
+ printf("base=%d, digits=%u, mode=%s, op=", base, n0,
+ mpfr_print_rnd_mode(rnd_mode));
+ mpfr_print_raw(op); putchar('\n');
+ exit(1);
}
}
ok = pow2 || mpfr_can_round(b, q-err, rnd_mode, rnd_mode, prec);
@@ -159,19 +175,34 @@ char *mpfr_get_str(str, expptr, base, n, op, rnd_mode)
else if ((rnd_mode==GMP_RNDU && neg==0) || (rnd_mode==GMP_RNDD && neg))
mpfr_sub(a, b, a, rnd_mode);
else mpfr_add(a, b, a, rnd_mode);
+#ifdef DEBUG
+ printf("a=%1.20e = ", mpfr_get_d(a)); mpfr_print_raw(a); putchar('\n');
+ printf("b=%1.20e = ", mpfr_get_d(b)); mpfr_print_raw(b); putchar('\n');
+#endif
/* check that a and b are rounded similarly */
prec=EXP(b);
+#ifdef DEBUG
+ printf("%d %d\n", EXP(a), prec);
+#endif
if (EXP(a) != prec) ok=0;
else {
mpfr_round(b, rnd_mode, prec);
mpfr_round(a, rnd_mode, prec);
+#ifdef DEBUG
+ printf("a=%1.20e = ", mpfr_get_d(a)); mpfr_print_raw(a); putchar('\n');
+ printf("b=%1.20e = ", mpfr_get_d(b)); mpfr_print_raw(b); putchar('\n');
+#endif
if (mpfr_cmp(a, b)) ok=0;
}
}
if (ok==0) { /* n is too large */
n--;
if (n==0) {
- fprintf(stderr, "cannot determine leading digit\n"); exit(1);
+ fprintf(stderr, "Error in mpfr_get_str: cannot determine leading digit\n");
+ printf("base=%d, digits=%u, mode=%s, op=", base, n0,
+ mpfr_print_rnd_mode(rnd_mode));
+ mpfr_print_raw(op); putchar('\n');
+ exit(1);
}
q -= BITS_PER_MP_LIMB;
}