summaryrefslogtreecommitdiff
path: root/mpfr
diff options
context:
space:
mode:
authorKevin Ryde <user42@zip.com.au>2001-02-01 23:29:23 +0100
committerKevin Ryde <user42@zip.com.au>2001-02-01 23:29:23 +0100
commit618be102b4c29f1e02e4a7d2244ae57b4bb544c9 (patch)
tree23f14ffeb18a23ed1c61258a65130fd2321bec75 /mpfr
parenteca14f894e34ab2d288357712157d6f942ced7fa (diff)
downloadgmp-618be102b4c29f1e02e4a7d2244ae57b4bb544c9.tar.gz
* mpfr/*: Update to mpfr 2001.
Tweaks applied to mpfr-impl.h for __gmp_allocate_func renaming, and to trunc.c for OPERATION_$* scheme.
Diffstat (limited to 'mpfr')
-rw-r--r--mpfr/add.c373
-rw-r--r--mpfr/add_ui.c54
-rw-r--r--mpfr/add_ulp.c34
-rw-r--r--mpfr/agm.c110
-rw-r--r--mpfr/clear.c6
-rw-r--r--mpfr/cmp.c115
-rw-r--r--mpfr/cmp_ui.c54
-rw-r--r--mpfr/cputime.h25
-rw-r--r--mpfr/div.c185
-rw-r--r--mpfr/div_2exp.c15
-rw-r--r--mpfr/div_ui.c73
-rw-r--r--mpfr/dump.c63
-rw-r--r--mpfr/eq.c135
-rw-r--r--mpfr/exp.c166
-rw-r--r--mpfr/exp2.c431
-rw-r--r--mpfr/exp3.c250
-rw-r--r--mpfr/extract.c66
-rw-r--r--mpfr/generic.c230
-rw-r--r--mpfr/get_str.c166
-rw-r--r--mpfr/init.c39
-rw-r--r--mpfr/inp_str.c105
-rw-r--r--mpfr/log.c95
-rw-r--r--mpfr/log2.c184
-rw-r--r--mpfr/mpf2mpfr.h144
-rw-r--r--mpfr/mpfr-impl.h123
-rw-r--r--mpfr/mpfr-test.h82
-rw-r--r--mpfr/mpfr.h234
-rw-r--r--mpfr/mpz_set_fr.c63
-rw-r--r--mpfr/mul.c67
-rw-r--r--mpfr/mul_2exp.c11
-rw-r--r--mpfr/mul_ui.c92
-rw-r--r--mpfr/neg.c18
-rw-r--r--mpfr/out_str.c27
-rw-r--r--mpfr/pi.c220
-rw-r--r--mpfr/pow.c96
-rw-r--r--mpfr/print_raw.c47
-rw-r--r--mpfr/print_rnd_mode.c10
-rw-r--r--mpfr/random.c56
-rw-r--r--mpfr/random2.c69
-rw-r--r--mpfr/reldiff.c76
-rw-r--r--mpfr/rnd_mode.c32
-rw-r--r--mpfr/round.c160
-rw-r--r--mpfr/set.c30
-rw-r--r--mpfr/set_d.c88
-rw-r--r--mpfr/set_dfl_prec.c9
-rw-r--r--mpfr/set_f.c24
-rw-r--r--mpfr/set_prc_raw.c49
-rw-r--r--mpfr/set_prec.c33
-rw-r--r--mpfr/set_q.c64
-rw-r--r--mpfr/set_rnd.c38
-rw-r--r--mpfr/set_si.c75
-rw-r--r--mpfr/set_str.c155
-rw-r--r--mpfr/set_str_raw.c48
-rw-r--r--mpfr/set_z.c34
-rw-r--r--mpfr/sin_cos.c246
-rw-r--r--mpfr/sqrt.c117
-rw-r--r--mpfr/sqrt_ui.c58
-rw-r--r--mpfr/sqrtrem.c225
-rw-r--r--mpfr/sub.c433
-rw-r--r--mpfr/sub_ui.c54
-rw-r--r--mpfr/swap.c59
-rw-r--r--mpfr/trunc.c185
-rw-r--r--mpfr/ui_div.c74
-rw-r--r--mpfr/ui_sub.c68
-rw-r--r--mpfr/urandomb.c78
65 files changed, 5431 insertions, 1414 deletions
diff --git a/mpfr/add.c b/mpfr/add.c
index c9bebe443..63cbb9109 100644
--- a/mpfr/add.c
+++ b/mpfr/add.c
@@ -1,6 +1,6 @@
/* mpfr_add -- add two floating-point numbers
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -23,9 +23,13 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
+
+/* #define DEBUG */
extern void mpfr_sub1 _PROTO((mpfr_ptr, mpfr_srcptr, mpfr_srcptr,
- unsigned char, int));
+ mp_rnd_t, int));
+void mpfr_add1 (mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t, int);
#define ONE ((mp_limb_t) 1)
@@ -35,14 +39,14 @@ extern void mpfr_sub1 _PROTO((mpfr_ptr, mpfr_srcptr, mpfr_srcptr,
void
#if __STDC__
-mpfr_add1(mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c,
- unsigned char rnd_mode, int diff_exp)
+mpfr_add1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c,
+ mp_rnd_t rnd_mode, int diff_exp)
#else
-mpfr_add1(a, b, c, rnd_mode, diff_exp)
- mpfr_ptr a;
- mpfr_srcptr b;
- mpfr_srcptr c;
- unsigned char rnd_mode;
+mpfr_add1 (a, b, c, rnd_mode, diff_exp)
+ mpfr_ptr a;
+ mpfr_srcptr b;
+ mpfr_srcptr c;
+ mp_rnd_t rnd_mode;
int diff_exp;
#endif
{
@@ -50,39 +54,46 @@ mpfr_add1(a, b, c, rnd_mode, diff_exp)
TMP_DECL(marker);
TMP_MARK(marker);
- ap = MANT(a);
- bp = MANT(b);
- cp = MANT(c);
+ ap = MPFR_MANT(a);
+ bp = MPFR_MANT(b);
+ cp = MPFR_MANT(c);
if (ap == bp) {
- bp = (mp_ptr) TMP_ALLOC(ABSSIZE(b) * BYTES_PER_MP_LIMB);
- MPN_COPY (bp, ap, ABSSIZE(b));
+ bp = (mp_ptr) TMP_ALLOC(MPFR_ABSSIZE(b) * BYTES_PER_MP_LIMB);
+ MPN_COPY (bp, ap, MPFR_ABSSIZE(b));
if (ap == cp) { cp = bp; }
}
else if (ap == cp)
{
- cp = (mp_ptr) TMP_ALLOC (ABSSIZE(c) * BYTES_PER_MP_LIMB);
- MPN_COPY(cp, ap, ABSSIZE(c));
+ cp = (mp_ptr) TMP_ALLOC (MPFR_ABSSIZE(c) * BYTES_PER_MP_LIMB);
+ MPN_COPY(cp, ap, MPFR_ABSSIZE(c));
}
- an = (PREC(a)-1)/mp_bits_per_limb+1; /* number of significant limbs of a */
+ an = (MPFR_PREC(a)-1)/BITS_PER_MP_LIMB+1; /* number of significant limbs of a */
- sh = an*mp_bits_per_limb-PREC(a); /* non-significant bits in low limb */
- bn = (PREC(b)-1)/mp_bits_per_limb+1; /* number of significant limbs of b */
- EXP(a) = EXP(b);
+ sh = an*BITS_PER_MP_LIMB-MPFR_PREC(a); /* non-significant bits in low limb */
+ bn = (MPFR_PREC(b)-1)/BITS_PER_MP_LIMB + 1; /* number of significant limbs of b */
+ cn = (MPFR_PREC(c)-1)/BITS_PER_MP_LIMB + 1;
+ MPFR_EXP(a) = MPFR_EXP(b);
- if (SIGN(a)!=SIGN(b)) CHANGE_SIGN(a);
+ if (MPFR_SIGN(a) * MPFR_SIGN(b) < 0) MPFR_CHANGE_SIGN(a);
/* case 1: diff_exp>=prec(a), i.e. c only affects the last bit
through rounding */
- dif = PREC(a)-diff_exp;
+ dif = MPFR_PREC(a)-diff_exp;
+#ifdef DEBUG
+ printf("diff_exp=%u dif=MPFR_PREC(a)-diff_exp=%d\n", diff_exp, dif);
+ printf("b= "); mpfr_print_raw(b); putchar('\n');
+ printf("c="); for (k=0;k<diff_exp;k++) putchar(' ');
+ if (MPFR_SIGN(c)>0) putchar(' '); mpfr_print_raw(c); putchar('\n');
+#endif
if (dif<=0) {
- /* diff_exp>=PREC(a): c does not overlap with a */
- /* either PREC(b)<=PREC(a), and we can copy the mantissa of b directly
- into that of a, or PREC(b)>PREC(a) and we have to round b+c */
+ /* diff_exp>=MPFR_PREC(a): c does not overlap with a */
+ /* either MPFR_PREC(b)<=MPFR_PREC(a), and we can copy the mantissa of b directly
+ into that of a, or MPFR_PREC(b)>MPFR_PREC(a) and we have to round b+c */
- if (PREC(b)<=PREC(a)) {
+ if (MPFR_PREC(b)<=MPFR_PREC(a)) {
MPN_COPY(ap+(an-bn), bp, bn);
/* fill low significant limbs with zero */
@@ -93,22 +104,22 @@ mpfr_add1(a, b, c, rnd_mode, diff_exp)
if (rnd_mode==GMP_RNDN) {
/* to nearest */
- /* if diff_exp > PREC(a), no change */
+ /* if diff_exp > MPFR_PREC(a), no change */
- if (diff_exp==PREC(a)) {
+ if (diff_exp==MPFR_PREC(a)) {
/* if c is not zero, then as it is normalized, we have to add
one to the lsb of a if c>1/2, or c=1/2 and lsb(a)=1 (round to
even) */
- if (NOTZERO(c)) {
+ if (MPFR_NOTZERO(c)) {
/* c is not zero */
/* check whether mant(c)=1/2 or not */
- cc = *cp - (ONE<<(mp_bits_per_limb-1));
+ cc = *cp - (ONE<<(BITS_PER_MP_LIMB-1));
if (cc==0) {
- bp = cp+(PREC(c)-1)/mp_bits_per_limb;
+ bp = cp+(MPFR_PREC(c)-1)/BITS_PER_MP_LIMB;
while (cp<bp && cc==0) cc = *++cp;
}
@@ -117,80 +128,88 @@ mpfr_add1(a, b, c, rnd_mode, diff_exp)
}
}
}
- else if ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
- (ISNEG(b) && rnd_mode==GMP_RNDD)) {
+ else if ((MPFR_ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
+ (MPFR_ISNEG(b) && rnd_mode==GMP_RNDD)) {
/* round up */
- if (NOTZERO(c)) goto add_one_ulp;
+ if (MPFR_NOTZERO(c)) goto add_one_ulp;
}
/* in the other cases (round to zero, or up/down with sign -/+),
nothing to do */
}
else {
- /* PREC(b)>PREC(a) : we have to round b+c */
+ /* MPFR_PREC(b)>MPFR_PREC(a) : we have to round b+c */
k=bn-an;
/* first copy the 'an' most significant limbs of b to a */
MPN_COPY(ap, bp+k, an);
- if (rnd_mode==GMP_RNDN) {
-
- /* to nearest */
- /* first check whether the truncated bits from b are 1/2*lsb(a) */
-
+ { /* treat all rounding modes together */
+ mp_limb_t c2old; long int cout=0; int sign=0;
if (sh) {
cc = *ap & ((ONE<<sh)-1);
*ap &= ~cc; /* truncate last bits */
- cc -= ONE<<(sh-1);
}
- else /* no bit to truncate */
- cc = bp[--k] - (ONE<<(mp_bits_per_limb-1));
-
- if ((long)cc>0) goto add_one_ulp; /* trunc(b)>1/2*lsb(a) -> round up */
- else if (cc==0) {
+ else cc=0;
- while (k>1 && cc==0) cc=bp[--k];
-
- /* now if the truncated part of b = 1/2*lsb(a), check whether c=0 */
- if (NOTZERO(c) || (*ap & (ONE<<sh))) goto add_one_ulp;
- /* if trunc(b)+c is exactly 1/2*lsb(a) : round to even lsb */
+ dif += sh;
+ if (dif>0) {
+ cn--;
+ c2old = cp[cn]; /* last limb from c considered */
+ cout += mpn_add_1(&cc, &cc, 1, c2old >> (BITS_PER_MP_LIMB-dif));
}
-
- /* if cc<0 : trunc(b) < 1/2*lsb(a) -> round down, i.e. do nothing */
- }
- else if ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
- (ISNEG(b) && rnd_mode==GMP_RNDD)) {
-
- /* first check whether trunc(b)+c is zero or not */
- if (sh) {
- cc = *ap & ((ONE<<sh)-1); *ap &= ~cc; /* truncate last bits */
+ else c2 = c2old = 0;
+ if (sh && rnd_mode==GMP_RNDN)
+ cout -= mpn_sub_1(&cc, &cc, 1, ONE<<(sh-1));
+ if (cout==0) {
+ dif += BITS_PER_MP_LIMB;
+ while (cout==0 && (k || cn)) {
+ cout = (cc>(mp_limb_t)1) ? 2 : cc;
+ cc = (k) ? bp[--k] : 0;
+ if (sh==0) {
+ cout -= mpn_sub_1(&cc, &cc, 1, ONE << (BITS_PER_MP_LIMB-1));
+ sh = 0;
+ }
+ /* next limb from c to consider is cp[cn-1], with lower part of
+ c2old */
+ c2 = c2old << dif;
+ if (cn && (dif>=0)) {
+ cn--;
+ c2old = cp[cn];
+ c2 += c2old >> (BITS_PER_MP_LIMB-dif);
+ }
+ else dif += BITS_PER_MP_LIMB;
+ cout += mpn_add_1(&cc, &cc, 1, c2);
+ }
}
- else cc = bp[--k] - (ONE<<(mp_bits_per_limb-1));
- while (cc==0 && k>1) cc=bp[--k];
- if (cc || NOTZERO(c)) goto add_one_ulp;
+ if (cout==0) cout=(cc!=0);
+ sign = (MPFR_ISNONNEG(b) && rnd_mode==GMP_RNDU)
+ || (MPFR_ISNEG(b) && rnd_mode==GMP_RNDD) || (rnd_mode==GMP_RNDN);
+ /* round towards infinity if dif=1, towards zero otherwise */
+ if ((sign==1) && (cout>0)) goto add_one_ulp;
+ else if (rnd_mode==GMP_RNDN && cout==0 && (*ap & (ONE<<sh)))
+ goto add_one_ulp;
}
-
- /* in the other cases (round to zero, or up/down with sign -/+),
- nothing to do, since b and c don't overlap, there can't be any
- carry */
-
}
}
else {
- /* diff_exp < PREC(a) : c overlaps with a by dif bits */
+ /* diff_exp < MPFR_PREC(a) : c overlaps with a by dif bits */
/* first copy upper part of c into a (after shift) */
unsigned char overlap;
- k = (dif-1)/mp_bits_per_limb + 1; /* only the highest k limbs from c
+ k = (dif-1)/BITS_PER_MP_LIMB + 1; /* only the highest k limbs from c
have to be considered */
- cn = (PREC(c)-1)/mp_bits_per_limb + 1;
+ cn = (MPFR_PREC(c)-1)/BITS_PER_MP_LIMB + 1;
MPN_ZERO(ap+k, an-k); /* do it now otherwise ap[k] may be destroyed
in case dif<0 */
- if (dif<=PREC(c)) {
+#ifdef DEBUG
+ printf("MPFR_PREC(c)=%d\n", MPFR_PREC(c));
+#endif
+ if (dif<=MPFR_PREC(c)) {
/* c has to be truncated */
- dif = dif % mp_bits_per_limb;
- dif = (dif) ? mp_bits_per_limb-dif-sh : -sh;
+ dif = dif % BITS_PER_MP_LIMB;
+ dif = (dif) ? BITS_PER_MP_LIMB-dif-sh : -sh;
/* we have to shift by dif bits to the right */
@@ -201,7 +220,7 @@ mpfr_add1(a, b, c, rnd_mode, diff_exp)
/* put the non-significant bits in low limb for further rounding */
if (cn >= k+1)
- ap[0] += cp[cn-k-1]>>(mp_bits_per_limb+dif);
+ ap[0] += cp[cn-k-1]>>(BITS_PER_MP_LIMB+dif);
}
else MPN_COPY(ap, cp+(cn-k), k);
overlap=1;
@@ -210,8 +229,8 @@ mpfr_add1(a, b, c, rnd_mode, diff_exp)
/* c is not truncated, but we have to fill low limbs with 0 */
- k = diff_exp/mp_bits_per_limb;
- overlap = diff_exp%mp_bits_per_limb;
+ k = diff_exp/BITS_PER_MP_LIMB;
+ overlap = diff_exp%BITS_PER_MP_LIMB;
/* warning: a shift of zero bit is not allowed */
MPN_ZERO(ap, an-k-cn);
@@ -227,135 +246,135 @@ mpfr_add1(a, b, c, rnd_mode, diff_exp)
/* then put high limbs to zero */
/* now add 'an' upper limbs of b in place */
- if (PREC(b)<=PREC(a)) {
+ if (MPFR_PREC(b)<=MPFR_PREC(a)) {
overlap += 2;
cc = mpn_add_n(ap+(an-bn), ap+(an-bn), bp, bn);
}
else
- /* PREC(b) > PREC(a): we have to truncate b */
+ /* MPFR_PREC(b) > MPFR_PREC(a): we have to truncate b */
cc = mpn_add_n(ap, ap, bp+(bn-an), an);
if (cc) {
/* shift one bit to the right */
- c3 = (ap[0]&1) && (PREC(a)%mp_bits_per_limb==0);
+ c3 = (ap[0]&1) && (MPFR_PREC(a)%BITS_PER_MP_LIMB==0);
mpn_rshift(ap, ap, an, 1);
- ap[an-1] += ONE<<(mp_bits_per_limb-1);
- EXP(a)++;
+ ap[an-1] += ONE<<(BITS_PER_MP_LIMB-1);
+ MPFR_EXP(a)++;
}
/* remains to do the rounding */
- if (rnd_mode==GMP_RNDN) {
-
- /* to nearest */
+#ifdef DEBUG
+ printf("overlap=%d\n", overlap);
+#endif
+ if (rnd_mode==GMP_RNDN || (MPFR_ISNONNEG(b) && rnd_mode==GMP_RNDU)
+ || (MPFR_ISNEG(b) && rnd_mode==GMP_RNDD)) {
int kc;
/* four cases: overlap =
- (0) PREC(b) > PREC(a) and diff_exp+PREC(c) <= PREC(a)
- (1) PREC(b) > PREC(a) and diff_exp+PREC(c) > PREC(a)
- (2) PREC(b) <= PREC(a) and diff_exp+PREC(c) <= PREC(a)
- (3) PREC(b) <= PREC(a) and diff_exp+PREC(c) > PREC(a) */
-
+ (0) MPFR_PREC(b) > MPFR_PREC(a) and diff_exp+MPFR_PREC(c) <= MPFR_PREC(a)
+ (1) MPFR_PREC(b) > MPFR_PREC(a) and diff_exp+MPFR_PREC(c) > MPFR_PREC(a)
+ (2) MPFR_PREC(b) <= MPFR_PREC(a) and diff_exp+MPFR_PREC(c) <= MPFR_PREC(a)
+ (3) MPFR_PREC(b) <= MPFR_PREC(a) and diff_exp+MPFR_PREC(c) > MPFR_PREC(a) */
+
switch (overlap)
- {
+ { mp_limb_t cout;
case 1: /* both b and c to round */
kc = cn-k; /* remains kc limbs from c */
k = bn-an; /* remains k limbs from b */
-
+
/* truncate last bits and store the difference with 1/2*ulp in cc */
cc = *ap & ((ONE<<sh)-1);
*ap &= ~cc; /* truncate last bits */
- cc -= ONE<<(sh-1);
- while ((cc==0 || cc==-1) && k!=0 && kc!=0) {
+ if (rnd_mode==GMP_RNDN)
+ cout = -mpn_sub_1(&cc, &cc, 1, ONE<<(sh-1));
+ else cout=0;
+ if ((~cout==0) && (~cc)) break;
+ cout = cc;
+ while ((cout==0 || cout==-1) && k!=0 && kc!=0) {
kc--;
- cc += mpn_add_1(&c2, bp+(--k), 1,(cp[kc+1]<<(mp_bits_per_limb-dif))
+ cout += mpn_add_1(&cc, bp+(--k), 1,(cp[kc+1]<<(BITS_PER_MP_LIMB-dif))
+(cp[kc]>>dif));
- if (cc==0 || cc==-1) cc=c2;
+ if (cout==0 || (~cout==0)) cout=cc;
+ }
+ if (kc==0 && dif) {
+ /* it still remains cp[0]<<(BITS_PER_MP_LIMB-dif) */
+ if (k!=0) cout += mpn_add_1(&cc, bp+(--k), 1,
+ cp[0]<<(BITS_PER_MP_LIMB-dif));
+ else cc = cp[0]<<(BITS_PER_MP_LIMB-dif);
+ if ((cout==0 && cc==0) || (~cout==0 && ~cc==0)) cout=cc;
+ }
+ if ((long)cout>0 || (cout==0 && cc)) goto add_one_ulp;
+ else if ((long)cout<0)
+ { TMP_FREE(marker); return; /* no carry possible any more */ }
+ else if (kc==0) {
+ while (k && cout==0) cout=bp[--k];
+ if ((~cout) && (cout || (rnd_mode==GMP_RNDN && (*ap & (ONE<<sh)))))
+ goto add_one_ulp;
+ else goto end_of_add;
}
- if ((long)cc>0) goto add_one_ulp;
- else if ((long)cc<-1)
- { TMP_FREE(marker); return; /* the carry can be at most 1 */ }
- else if (kc==0) goto round_b;
/* else round c: go through */
case 3: /* only c to round */
- bp=cp; k=cn-k; goto to_nearest;
+ bp=cp; k=cn-k; bn=cn;
+ goto to_nearest;
case 0: /* only b to round */
- round_b:
- k=bn-an; dif=0; goto to_nearest;
+ k=bn-an; dif=0;
+ goto to_nearest;
/* otherwise the result is exact: nothing to do */
}
}
- else if ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
- (ISNEG(b) && rnd_mode==GMP_RNDD)) {
- cc = *ap & ((ONE<<sh)-1);
- *ap &= ~cc; /* truncate last bits */
- if (cc || c3) goto add_one_ulp; /* will happen most of the time */
- else {
-
- /* same four cases too */
-
- int kc = cn-k; /* remains kc limbs from c */
- switch (overlap)
- {
- case 1: /* both b and c to round */
- k = bn-an; /* remains k limbs from b */
- while (cc==0 && k!=0 && kc!=0) {
- kc--;
- cc = mpn_add_1(&c2, bp+(--k), 1,(cp[kc+1]<<(mp_bits_per_limb-dif))
- + (cp[kc]>>dif));
- }
- if (cc) goto add_one_ulp;
- else if (kc==0) goto round_b2;
- /* else round c: go through */
- case 3: /* only c to round */
- while (kc) if (cp[--kc]) goto add_one_ulp;
- /* if dif>0 : remains to check last dif bits from c */
- if (dif>0 && (cp[0]<<(mp_bits_per_limb-dif))) goto add_one_ulp;
- break;
- case 0: /* only b to round */
- round_b2:
- k=bn-an;
- while (k) if (bp[--k]) goto add_one_ulp;
- /* otherwise the result is exact: nothing to do */
- }
- }
- }
/* else nothing to do: round towards zero, i.e. truncate last sh bits */
else
*ap &= ~((ONE<<sh)-1);
}
goto end_of_add;
- to_nearest: /* 0 <= sh < mp_bits_per_limb : number of bits of a to truncate
- bp[k] : last significant limb from b */
+ to_nearest: /* 0 <= sh < BITS_PER_MP_LIMB : number of bits of a to truncate
+ bp[k] : last significant limb from b
+ bn : number of limbs of b
+ */
+ /* c3=1 whenever b+c gave a carry out in most significant limb
+ and the least significant bit (shifted right) was 1.
+ This can occur only when BITS_PER_MP_LIMB divides MPFR_PREC(a),
+ i.e. sh=0.
+ */
if (sh) {
cc = *ap & ((ONE<<sh)-1);
*ap &= ~cc; /* truncate last bits */
- c2 = ONE<<(sh-1);
+ c2 = (rnd_mode==GMP_RNDN) ? ONE<<(sh-1) : 0;
}
- else /* no bit to truncate */
- { if (k) cc = bp[--k]; else cc = 0; c2 = ONE<<(mp_bits_per_limb-1); }
+ else /* sh=0: no bit to truncate */
+ {
+ if (k) cc = bp[--k]; else cc = 0;
+ c2 = (rnd_mode==GMP_RNDN) ? ONE<<(BITS_PER_MP_LIMB-1) : 0;
+ if (c3 && (cc || c2==0)) cc=c2+1; /* will force adding one ulp */
+ }
if (cc>c2) goto add_one_ulp; /* trunc(b)>1/2*lsb(a) -> round up */
else if (cc==c2) {
- cc=0; while (k && cc==0) cc=bp[--k];
/* special case of rouding c shifted to the right */
- if (cc==0 && dif>0) cc=cp[0]<<(mp_bits_per_limb-dif);
+ if (dif>0 && k<bn) cc=bp[k]<<(BITS_PER_MP_LIMB-dif);
+ else cc=0;
+ while (k && cc==0) cc=bp[--k];
/* now if the truncated part of b = 1/2*lsb(a), check whether c=0 */
- if (cc || (*ap & (ONE<<sh))) goto add_one_ulp;
+ if (cc || (rnd_mode==GMP_RNDN && (*ap & (ONE<<sh))))
+ goto add_one_ulp;
}
goto end_of_add;
add_one_ulp: /* add one unit in last place to a */
cc = mpn_add_1(ap, ap, an, ONE<<sh);
- if (cc) { fprintf(stderr, "carry(3) in mpfr_add\n"); exit(1); }
+ if (cc) {
+ ap[an-1] = (mp_limb_t)1 << (BITS_PER_MP_LIMB-1);
+ MPFR_EXP(a)++;
+ }
end_of_add:
TMP_FREE(marker);
@@ -364,27 +383,57 @@ mpfr_add1(a, b, c, rnd_mode, diff_exp)
void
#if __STDC__
-mpfr_add(mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c,
- unsigned char rnd_mode)
+mpfr_add (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mp_rnd_t rnd_mode)
#else
-mpfr_add(a, b, c, rnd_mode)
- mpfr_ptr a;
- mpfr_srcptr b;
- mpfr_srcptr c;
- unsigned char rnd_mode;
+mpfr_add (a, b, c, rnd_mode)
+ mpfr_ptr a;
+ mpfr_srcptr b;
+ mpfr_srcptr c;
+ mp_rnd_t rnd_mode;
#endif
{
int diff_exp;
- if (FLAG_NAN(b) || FLAG_NAN(c)) {
- SET_NAN(a); return;
+ if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c)) {
+ MPFR_SET_NAN(a); return;
}
+
+ MPFR_CLEAR_NAN(a);
+
+ if (MPFR_IS_INF(b))
+ {
+ if (MPFR_IS_INF(c))
+ {
+ if (MPFR_SIGN(b) == MPFR_SIGN(c))
+ {
+ MPFR_SET_INF(a);
+ if (MPFR_SIGN(a) != MPFR_SIGN(b)) MPFR_CHANGE_SIGN(a);
+ }
+ else
+ MPFR_SET_NAN(a);
+ }
+ else
+ {
+ MPFR_SET_INF(a);
+ if (MPFR_SIGN(b) != MPFR_SIGN(a)) MPFR_CHANGE_SIGN(a);
+ }
+ return;
+ }
+ else
+ if (MPFR_IS_INF(c))
+ {
+ MPFR_SET_INF(a);
+ if (MPFR_SIGN(c) != MPFR_SIGN(a)) MPFR_CHANGE_SIGN(a);
+ return;
+ }
+
+ MPFR_CLEAR_INF(a); /* clear Inf flag */
- if (!NOTZERO(b)) { mpfr_set(a, c, rnd_mode); return; }
- if (!NOTZERO(c)) { mpfr_set(a, b, rnd_mode); return; }
+ if (!MPFR_NOTZERO(b)) { mpfr_set(a, c, rnd_mode); return; }
+ if (!MPFR_NOTZERO(c)) { mpfr_set(a, b, rnd_mode); return; }
- diff_exp = EXP(b)-EXP(c);
- if (SIGN(b) != SIGN(c)) { /* signs differ, it's a subtraction */
+ diff_exp = MPFR_EXP(b)-MPFR_EXP(c);
+ if (MPFR_SIGN(b) * MPFR_SIGN(c) < 0) { /* signs differ, it's a subtraction */
if (diff_exp<0) {
mpfr_sub1(a, c, b, rnd_mode, -diff_exp);
}
@@ -392,8 +441,8 @@ mpfr_add(a, b, c, rnd_mode)
else { /* diff_exp=0 */
diff_exp = mpfr_cmp3(b,c,-1);
/* if b>0 and diff_exp>0 or b<0 and diff_exp<0: abs(b) > abs(c) */
- if (diff_exp==0) SET_ZERO(a);
- else if (diff_exp*SIGN(b)>0) mpfr_sub1(a, b, c, rnd_mode, 0);
+ if (diff_exp==0) MPFR_SET_ZERO(a);
+ else if (diff_exp * MPFR_SIGN(b)>0) mpfr_sub1(a, b, c, rnd_mode, 0);
else mpfr_sub1(a, c, b, rnd_mode, 0);
}
}
diff --git a/mpfr/add_ui.c b/mpfr/add_ui.c
new file mode 100644
index 000000000..43c08e316
--- /dev/null
+++ b/mpfr/add_ui.c
@@ -0,0 +1,54 @@
+/* mpfr_add_ui -- add a floating-point number with a machine integer
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+void
+#if __STDC__
+mpfr_add_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mp_rnd_t rnd_mode)
+#else
+mpfr_add_ui (y, x, u, rnd_mode)
+ mpfr_ptr y;
+ mpfr_srcptr x;
+ unsigned long int u;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ mpfr_t uu;
+ mp_limb_t up[1];
+ unsigned long cnt;
+
+ if (u) { /* if u=0, do nothing */
+ MPFR_INIT1(up, uu, BITS_PER_MP_LIMB, 1);
+ count_leading_zeros(cnt, (mp_limb_t) u);
+ *up = (mp_limb_t) u << cnt;
+ MPFR_EXP(uu) = BITS_PER_MP_LIMB-cnt;
+
+ mpfr_add(y, x, uu, rnd_mode);
+ }
+ else
+ mpfr_set (y, x, rnd_mode);
+}
diff --git a/mpfr/add_ulp.c b/mpfr/add_ulp.c
index 7a8fa6150..d94fd73b6 100644
--- a/mpfr/add_ulp.c
+++ b/mpfr/add_ulp.c
@@ -1,6 +1,6 @@
/* mpfr_add_one_ulp, mpfr_sub_one_ulp -- add/subtract one unit in last place
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -20,11 +20,12 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include "gmp.h"
-#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
+#include "gmp-impl.h"
-/* sets x to x+sign(x)*2^(EXP(x)-PREC(x)) */
-int
+/* sets x to x+sign(x)*2^(MPFR_EXP(x)-MPFR_PREC(x)) */
+void
#if __STDC__
mpfr_add_one_ulp(mpfr_ptr x)
#else
@@ -34,31 +35,34 @@ mpfr_add_one_ulp(x)
{
int xn, sh; mp_limb_t *xp;
- xn = 1 + (PREC(x)-1)/BITS_PER_MP_LIMB;
- sh = xn*BITS_PER_MP_LIMB - PREC(x);
- xp = MANT(x);
+ if (MPFR_IS_INF(x)) { return; }
+ xn = 1 + (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB;
+ sh = xn*BITS_PER_MP_LIMB - MPFR_PREC(x);
+ xp = MPFR_MANT(x);
if (mpn_add_1(xp, xp, xn, (mp_limb_t)1<<sh)) {
- EXP(x)++;
+ MPFR_EXP(x)++;
mpn_rshift(xp, xp, xn, 1);
xp[xn-1] += (mp_limb_t)1<<(BITS_PER_MP_LIMB-1);
}
- return 0;
+ return;
}
/* sets x to x-sign(x)*ulp(x) */
-int mpfr_sub_one_ulp(mpfr_ptr x)
+void
+mpfr_sub_one_ulp(mpfr_ptr x)
{
int xn, sh; mp_limb_t *xp;
- xn = 1 + (PREC(x)-1)/BITS_PER_MP_LIMB;
- sh = xn*BITS_PER_MP_LIMB-PREC(x);
- xp = MANT(x);
+ if (MPFR_IS_INF(x)) { return; }
+ xn = 1 + (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB;
+ sh = xn*BITS_PER_MP_LIMB-MPFR_PREC(x);
+ xp = MPFR_MANT(x);
mpn_sub_1(xp, xp, xn, (mp_limb_t)1<<sh);
if (xp[xn-1] >> (BITS_PER_MP_LIMB-1) == 0) {
/* was an exact power of two: not normalized any more */
- EXP(x)--;
+ MPFR_EXP(x)--;
mpn_lshift(xp, xp, xn, 1);
*xp |= ((mp_limb_t)1 << sh);
}
- return 0;
+ return;
}
diff --git a/mpfr/agm.c b/mpfr/agm.c
index e4c700961..75b5762d3 100644
--- a/mpfr/agm.c
+++ b/mpfr/agm.c
@@ -1,6 +1,6 @@
/* mpfr_agm -- arithmetic-geometric mean of two floating-point numbers
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -20,72 +20,105 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include <stdio.h>
-#include <math.h>
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
+/* returns ceil(log(d)/log(2)) */
+long _mpfr_ceil_log2 (double d)
+{
+ long exp;
+ union ieee_double_extract x;
+
+ x.d = d;
+ exp = x.s.exp - 1023;
+ x.s.exp = 1023; /* value for 1 <= d < 2 */
+ if (x.d != 1.0) exp++;
+ return exp;
+}
-/*Memory gestion */
-#define MON_INIT(xp, x, p, s) xp = (mp_ptr) TMP_ALLOC(s*BYTES_PER_MP_LIMB); x -> _mp_prec = p; x -> _mp_d = xp; x -> _mp_size = s; x -> _mp_exp = 0;
-
+/* returns floor(log(d)/log(2)) */
+long _mpfr_floor_log2 (double d)
+{
+ union ieee_double_extract x;
+ x.d = d;
+ return (long) x.s.exp - 1023;
+}
+/* returns y >= 2^d */
+double _mpfr_ceil_exp2 (double d)
+{
+ long exp;
+ union ieee_double_extract x;
+
+ exp = (long) d;
+ if (d != (double) exp) exp++;
+ /* now exp = ceil(d) */
+ x.d = 1.0;
+ x.s.exp = 1023 + exp;
+ return x.d;
+}
void
#ifdef __STDC__
-mpfr_agm(mpfr_ptr r, mpfr_srcptr op2, mpfr_srcptr op1, unsigned char rnd_mode)
+mpfr_agm (mpfr_ptr r, mpfr_srcptr op2, mpfr_srcptr op1, mp_rnd_t rnd_mode)
#else
-mpfr_agm(r, a, b, rnd_mode)
- mpfr_ptr r;
- mpfr_srcptr a;
- mpfr_srcptr b;
- unsigned char rnd_mode;
+mpfr_agm (r, op2, op1, rnd_mode)
+ mpfr_ptr r;
+ mpfr_srcptr op2;
+ mpfr_srcptr op1;
+ mp_rnd_t rnd_mode;
#endif
{
- int s, p, q, go_on;
+ int s, go_on;
+ mp_prec_t p, q;
double uo, vo;
mp_limb_t *up, *vp, *tmpp, *tmpup, *tmpvp, *ap, *bp;
mpfr_t u, v, tmp, tmpu, tmpv, a, b;
TMP_DECL(marker1);
TMP_DECL(marker2);
-
/* If a or b is NaN, the result is NaN */
- if (FLAG_NAN(op1) || FLAG_NAN(op2))
- { SET_NAN(r); return; }
+ if (MPFR_IS_NAN(op1) || MPFR_IS_NAN(op2))
+ { MPFR_SET_NAN(r); return; }
+ /* If a or b is negative (including -Infinity), the result is NaN */
+ if ((MPFR_SIGN(op1) < 0) || (MPFR_SIGN(op2) < 0))
+ { MPFR_SET_NAN(r); return; }
- /* If a or b is negative, the result is NaN */
- if ((SIGN(op1)<0)||(SIGN(op2)<0))
- { SET_NAN(r); return; }
+ MPFR_CLEAR_NAN(r);
+ /* If a or b is +Infinity, the result is +Infinity */
+ if (MPFR_IS_INF(op1) || MPFR_IS_INF(op2))
+ { MPFR_SET_INF(r); MPFR_SET_SAME_SIGN(r, op1); return; }
+ MPFR_CLEAR_INF(r);
/* If a or b is 0, the result is 0 */
- if ((SIGN(op1)==0)||(SIGN(op2)==0))
- { SET_ZERO(r);
+ if ((MPFR_NOTZERO(op1) && MPFR_NOTZERO(op2)) == 0)
+ { MPFR_SET_ZERO(r);
return;
}
/* precision of the following calculus */
- q = PREC(r);
+ q = MPFR_PREC(r);
p = q + 15;
-
/* Initialisations */
go_on=1;
TMP_MARK(marker1);
s=(p-1)/BITS_PER_MP_LIMB+1;
- MON_INIT(ap, a, p, s);
- MON_INIT(bp, b, p, s);
+ MPFR_INIT(ap, a, p, s);
+ MPFR_INIT(bp, b, p, s);
TMP_MARK(marker2);
- MON_INIT(up, u, p, s);
- MON_INIT(vp, v, p, s);
- MON_INIT(tmpup, tmpu, p, s);
- MON_INIT(tmpvp, tmpv, p, s);
- MON_INIT(tmpp, tmp, p, s);
+ MPFR_INIT(up, u, p, s);
+ MPFR_INIT(vp, v, p, s);
+ MPFR_INIT(tmpup, tmpu, p, s);
+ MPFR_INIT(tmpvp, tmpv, p, s);
+ MPFR_INIT(tmpp, tmp, p, s);
@@ -111,16 +144,19 @@ mpfr_agm(r, a, b, rnd_mode)
eq=0;
- err=ceil((3.0/2.0*log((double)p)/log(2.0)+1.0)*exp(-(double)p*log(2.0))+3.0*exp(-2.0*(double)p*uo*log(2.0)/(vo-uo)));
+ err=1 + (int) ((3.0/2.0*_mpfr_ceil_log2(p)+1.0)*_mpfr_ceil_exp2(-(double)p)
+ +3.0*_mpfr_ceil_exp2(-2.0*(double)p*uo/(vo-uo)));
if(p-err-3<=q) {
p=q+err+4;
- err=ceil((3.0/2.0*log((double)p)/log(2.0)+1.0)*exp(-(double)p*log(2.0))+3.0*exp(-2.0*(double)p*uo*log(2.0)/(vo-uo)));
+ err= 1 +
+ (int) ((3.0/2.0*_mpfr_ceil_log2(p)+1.0)*_mpfr_ceil_exp2(-(double)p)
+ +3.0*_mpfr_ceil_exp2(-2.0*(double)p*uo/(vo-uo)));
}
/* Calculus of un and vn */
while (eq<=p-2) {
mpfr_mul(tmp,u,v,GMP_RNDN);
- mpfr_sqrt(tmpu,tmp,GMP_RNDN);
+ mpfr_sqrt (tmpu, tmp, GMP_RNDN);
mpfr_add(tmp,u,v,GMP_RNDN);
mpfr_div_2exp(tmpv,tmp,1,GMP_RNDN);
mpfr_set(u,tmpu,GMP_RNDN);
@@ -148,11 +184,11 @@ mpfr_agm(r, a, b, rnd_mode)
TMP_FREE(marker2);
TMP_MARK(marker2);
s=(p-1)/BITS_PER_MP_LIMB+1;
- MON_INIT(up, u, p, s);
- MON_INIT(vp, v, p, s);
- MON_INIT(tmpup, tmpu, p, s);
- MON_INIT(tmpvp, tmpv, p, s);
- MON_INIT(tmpp, tmp, p, s);
+ MPFR_INIT(up, u, p, s);
+ MPFR_INIT(vp, v, p, s);
+ MPFR_INIT(tmpup, tmpu, p, s);
+ MPFR_INIT(tmpvp, tmpv, p, s);
+ MPFR_INIT(tmpp, tmp, p, s);
mpfr_set(u,a,GMP_RNDN);
mpfr_set(v,b,GMP_RNDN);
}
diff --git a/mpfr/clear.c b/mpfr/clear.c
index dfa4771c5..5f492badf 100644
--- a/mpfr/clear.c
+++ b/mpfr/clear.c
@@ -1,6 +1,6 @@
/* mpfr_clear -- free the memory space allocated for a floating-point number
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -23,6 +23,7 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
void
#if __STDC__
@@ -32,5 +33,6 @@ mpfr_clear (m)
mpfr_ptr m;
#endif
{
- (*__gmp_free_func) (m->_mp_d, ((m->_mp_prec>>3) + 1));
+ /* be careful to always free an entire number of limbs */
+ (*_mp_free_func) (MPFR_MANT(m), MPFR_ABSSIZE(m) * BYTES_PER_MP_LIMB);
}
diff --git a/mpfr/cmp.c b/mpfr/cmp.c
index b64506b03..d0cb175db 100644
--- a/mpfr/cmp.c
+++ b/mpfr/cmp.c
@@ -1,6 +1,6 @@
/* mpfr_cmp -- compare two floating-point numbers
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -24,6 +24,7 @@ MA 02111-1307, USA. */
#include "gmp-impl.h"
#include "longlong.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
/* returns 0 iff b = c
a positive value iff b > c
@@ -41,9 +42,9 @@ of b and c, i.e. one plus the number of bits shifts to align b and c
/* compares b and sign(s)*c */
int
#if __STDC__
-mpfr_cmp3 ( mpfr_srcptr b, mpfr_srcptr c, long int s)
+mpfr_cmp3 (mpfr_srcptr b, mpfr_srcptr c, long int s)
#else
-mpfr_cmp3(b, c, s)
+mpfr_cmp3 (b, c, s)
mpfr_srcptr b;
mpfr_srcptr c;
long int s;
@@ -53,22 +54,34 @@ mpfr_cmp3(b, c, s)
unsigned long bn, cn;
mp_limb_t *bp, *cp;
- if (!NOTZERO(b) && !NOTZERO(c)) { return 0; }
- s = s*SIGN(b)*SIGN(c);
- if (s<0) return(SIGN(b));
+ if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c)) return 1;
- /* now signs are equal */
+ if (MPFR_IS_INF(b)) {
+ if (MPFR_IS_INF(c) && (MPFR_SIGN(b) * s * MPFR_SIGN(c) > 0))
+ return 0;
+ else
+ return MPFR_SIGN(b);
+ }
+
+ if (!MPFR_NOTZERO(b)) {
+ if (!MPFR_NOTZERO(c)) return 0; else return -(s*MPFR_SIGN(c));
+ }
+ else if (!MPFR_NOTZERO(c)) return MPFR_SIGN(b);
- diff_exp = EXP(b)-EXP(c);
- s = (SIGN(b)>0) ? 1 : -1;
+ s = s * MPFR_SIGN(b) * MPFR_SIGN(c);
+ if (s<0) return(MPFR_SIGN(b));
+
+ /* now signs are equal */
+ diff_exp = MPFR_EXP(b)-MPFR_EXP(c);
+ s = (MPFR_SIGN(b) > 0) ? 1 : -1;
if (diff_exp>0) return(s*(1+diff_exp));
else if (diff_exp<0) return(s*(-1+diff_exp));
/* both signs and exponents are equal */
- bn = (PREC(b)-1)/mp_bits_per_limb+1;
- cn = (PREC(c)-1)/mp_bits_per_limb+1;
- bp = MANT(b); cp = MANT(c);
+ bn = (MPFR_PREC(b)-1)/BITS_PER_MP_LIMB+1;
+ cn = (MPFR_PREC(c)-1)/BITS_PER_MP_LIMB+1;
+ bp = MPFR_MANT(b); cp = MPFR_MANT(c);
while (bn && cn) {
if (bp[--bn] != cp[--cn])
@@ -82,8 +95,10 @@ mpfr_cmp3(b, c, s)
}
/* returns the number of cancelled bits when one subtracts abs(c) from abs(b).
- Assumes b>=c, which implies EXP(b)>=EXP(c).
+ Assumes b>=c, which implies MPFR_EXP(b)>=MPFR_EXP(c).
if b=c, returns prec(b).
+
+ In other terms mpfr_cmp2 (b, c) returns EXP(b) - EXP(b-c).
*/
int
#if __STDC__
@@ -101,44 +116,45 @@ mpfr_cmp2(b, c)
printf("b="); mpfr_print_raw(b); putchar('\n');
printf("c="); mpfr_print_raw(c); putchar('\n');
#endif
- if (NOTZERO(c)==0) return (NOTZERO(b)) ? 0 : PREC(b);
- d = EXP(b)-EXP(c);
+ if (MPFR_NOTZERO(c)==0) return (MPFR_NOTZERO(b)) ? 0 : MPFR_PREC(b);
+ d = MPFR_EXP(b)-MPFR_EXP(c);
k = 0; /* result can be d or d+1 if d>1, or >= d otherwise */
/* k is the number of identical bits in the high part,
then z is the number of possibly cancelled bits */
#ifdef DEBUG
- if (d<0) { printf("assumption EXP(b)<EXP(c) violated\n"); exit(1); }
+ printf("d=%u\n", d);
+ if (d<0) { printf("assumption MPFR_EXP(b)<MPFR_EXP(c) violated\n"); exit(1); }
#endif
- bn = (PREC(b)-1)/mp_bits_per_limb;
- cn = (PREC(c)-1)/mp_bits_per_limb;
- bp = MANT(b); cp = MANT(c);
+ bn = (MPFR_PREC(b)-1)/BITS_PER_MP_LIMB;
+ cn = (MPFR_PREC(c)-1)/BITS_PER_MP_LIMB;
+ bp = MPFR_MANT(b); cp = MPFR_MANT(c);
/* subtract c from b from most significant to less significant limbs,
and first determines first non zero limb difference */
if (d)
{
cc = bp[bn--];
- if (d<mp_bits_per_limb)
- cc -= cp[cn]>>d;
+ if (d < BITS_PER_MP_LIMB)
+ cc -= cp[cn] >> d;
}
else { /* d=0 */
while (bn>=0 && cn>=0 && (cc=(bp[bn--]-cp[cn--]))==0) {
- k+=mp_bits_per_limb;
+ k+=BITS_PER_MP_LIMB;
}
if (cc==0) { /* either bn<0 or cn<0 */
- while (bn>=0 && (cc=bp[bn--])==0) k+=mp_bits_per_limb;
+ while (bn>=0 && (cc=bp[bn--])==0) k+=BITS_PER_MP_LIMB;
}
/* now bn<0 or cc<>0 */
- if (cc==0 && bn<0) return(PREC(b));
+ if (cc==0 && bn<0) return(MPFR_PREC(b));
}
/* the first non-zero limb difference is cc, and the number
of cancelled bits in the upper limbs is k */
count_leading_zeros(u, cc);
- k += u;
+ k += u;
- if (cc != (1<<(mp_bits_per_limb-u-1))) return k;
+ if (cc != ((mp_limb_t) 1 << (BITS_PER_MP_LIMB - u - 1))) return k;
/* now cc is an exact power of two */
if (cc != 1)
@@ -151,11 +167,11 @@ mpfr_cmp2(b, c)
{
if (cn < 0) { return k; }
t = bp[bn--];
- if (d < mp_bits_per_limb)
+ if (d < BITS_PER_MP_LIMB)
{
if (d)
{
- u = cp[cn--] << (mp_bits_per_limb - d);
+ u = cp[cn--] << (BITS_PER_MP_LIMB - d);
if (cn >= 0) u+=(cp[cn]>>d);
}
else u = cp[cn--];
@@ -164,12 +180,12 @@ mpfr_cmp2(b, c)
if (t < u) return k+1;
}
else
- if (t) return k; else d -= mp_bits_per_limb;
+ if (t) return k; else d -= BITS_PER_MP_LIMB;
}
/* bn < 0; if some limb of c is nonzero, return k+1, otherwise return k*/
- if (cn>=0 && (cp[cn--] << (mp_bits_per_limb - d))) { return k+1; }
+ if (cn>=0 && (cp[cn--] << (BITS_PER_MP_LIMB - d))) { return k+1; }
while (cn >= 0)
if (cp[cn--]) return k+1;
@@ -180,16 +196,18 @@ mpfr_cmp2(b, c)
z = 0; /* number of possibly cancelled bits - 1 */
/* thus result is either k if low(b) >= low(c)
or k+z+1 if low(b) < low(c) */
- if (d > mp_bits_per_limb) { return k; }
+ if (d > BITS_PER_MP_LIMB) return k;
- while (bn >= 0)
+ while (bn >= 0) /* the next limb of b to be considered is b[bn] */
{
- if (cn < 0) { return k; }
+ /* for c we have to consider the low d bits of c[cn]
+ and the high (BITS_PER_MP_LIMB-d) bits of c[cn-1] */
+ if (cn < 0) return k;
if (d)
{
- u = cp[cn--] << (mp_bits_per_limb - d);
- if (cn >= 0) u+=(cp[cn]>>d);
+ u = cp[cn--] << (BITS_PER_MP_LIMB - d);
+ if (cn >= 0) u += cp[cn] >> d;
}
else u = cp[cn--];
@@ -198,21 +216,30 @@ mpfr_cmp2(b, c)
bp[bn--] < cp[cn--] : borrow
*/
if ((cc = bp[bn--]) != u) {
- if (cc>u) return k;
- else { count_leading_zeros(u, cc-u); return k + 1 + z + u; }
+ if (cc > u) return k;
+ else {
+ count_leading_zeros(u, cc-u);
+ z += u + 1;
+ if (u + 1 < BITS_PER_MP_LIMB) return k + z;
+ }
}
- else z += mp_bits_per_limb;
+ else z += BITS_PER_MP_LIMB;
}
- if (cn >= 0)
- count_leading_zeros(cc, ~(cp[cn--] << (mp_bits_per_limb - d)));
- else { cc = 0; }
+ /* warning: count_leading_zeros doesn't work with zero */
+ if ((cn >= 0) && d && (u = ~(cp[cn--] << (BITS_PER_MP_LIMB - d))))
+ count_leading_zeros(cc, u);
+ else
+ cc = 0;
- k += cc;
+ /* here d=0 or d=1: if d=1, we have one more cancelled bit if we don't
+ shift cp[cn] */
+ k += cc;
if (cc < d) return k;
- while (cn >= 0 && !~cp[cn--]) { z += mp_bits_per_limb; }
- if (cn >= 0) { count_leading_zeros(cc, ~cp[cn--]); return (k + z + cc); }
+ while (cn >= 0 && !~cp[cn]) { z += BITS_PER_MP_LIMB; cn--; }
+ /* now either cn<0 or cp[cn] is not 111...111 */
+ if (cn >= 0) { count_leading_zeros(cc, ~cp[cn]); return (k + 1 + z + cc); }
return k; /* We **need** that the nonsignificant limbs of c are set
to zero there */
diff --git a/mpfr/cmp_ui.c b/mpfr/cmp_ui.c
index 48217a520..364881970 100644
--- a/mpfr/cmp_ui.c
+++ b/mpfr/cmp_ui.c
@@ -1,6 +1,6 @@
/* mpfr_cmp_ui -- compare a floating-point number with a machine integer
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -24,6 +24,7 @@ MA 02111-1307, USA. */
#include "gmp-impl.h"
#include "longlong.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
/* returns a positive value if b>i*2^f,
a negative value if b<i*2^f,
@@ -32,7 +33,7 @@ MA 02111-1307, USA. */
int
#if __STDC__
-mpfr_cmp_ui_2exp ( mpfr_srcptr b, unsigned long int i, int f )
+mpfr_cmp_ui_2exp (mpfr_srcptr b, unsigned long int i, int f )
#else
mpfr_cmp_ui_2exp (b, i, f)
mpfr_srcptr b;
@@ -42,21 +43,27 @@ mpfr_cmp_ui_2exp (b, i, f)
{
int e, k, bn; mp_limb_t c, *bp;
- if (SIGN(b)<0) return -1;
- else if (!NOTZERO(b)) return((i) ? -1 : 0);
- else { /* b>0 */
- e = EXP(b); /* 2^(e-1) <= b < 2^e */
- if (e>f+mp_bits_per_limb) return 1;
+ if (MPFR_IS_NAN(b)) return 1;
+
+ if (MPFR_SIGN(b) < 0) return -1;
+ /* now b>=0 */
+ else if (MPFR_IS_INF(b)) return 1;
+ else if (!MPFR_NOTZERO(b)) return((i) ? -1 : 0);
+ /* now b>0 */
+ else if (i==0) return 1;
+ else { /* b>0, i>0 */
+ e = MPFR_EXP(b); /* 2^(e-1) <= b < 2^e */
+ if (e>f+BITS_PER_MP_LIMB) return 1;
c = (mp_limb_t) i;
count_leading_zeros(k, c);
- k = f+mp_bits_per_limb - k; /* 2^(k-1) <= i*2^f < 2^k */
+ k = f+BITS_PER_MP_LIMB - k; /* 2^(k-1) <= i*2^f < 2^k */
if (k!=e) return (e-k);
/* now k=e */
- c <<= (f+mp_bits_per_limb-k);
- bn = (PREC(b)-1)/mp_bits_per_limb;
- bp = MANT(b) + bn;
+ c <<= (f+BITS_PER_MP_LIMB-k);
+ bn = (MPFR_PREC(b)-1)/BITS_PER_MP_LIMB;
+ bp = MPFR_MANT(b) + bn;
if (*bp>c) return 1;
else if (*bp<c) return -1;
@@ -74,9 +81,9 @@ mpfr_cmp_ui_2exp (b, i, f)
int
#if __STDC__
-mpfr_cmp_si_2exp ( mpfr_srcptr b, long int i, int f )
+mpfr_cmp_si_2exp (mpfr_srcptr b, long int i, int f )
#else
-mpfr_cmp_si_2exp(b, i, f)
+mpfr_cmp_si_2exp (b, i, f)
mpfr_srcptr b;
long int i;
int f;
@@ -84,26 +91,29 @@ mpfr_cmp_si_2exp(b, i, f)
{
int e, k, bn, si; mp_limb_t c, *bp;
+ if (MPFR_IS_NAN(b)) return 1;
+
si = (i<0) ? -1 : 1; /* sign of i */
- if (SIGN(b)*i<0) return SIGN(b); /* both signs differ */
- else if (!NOTZERO(b) || (i==0)) { /* one is zero */
- if (i==0) return ((NOTZERO(b)) ? SIGN(b) : 0);
+ if (MPFR_SIGN(b) * i < 0 || MPFR_IS_INF(b)) return MPFR_SIGN(b);
+ /* both signs differ */
+ else if (!MPFR_NOTZERO(b) || (i==0)) { /* one is zero */
+ if (i==0) return ((MPFR_NOTZERO(b)) ? MPFR_SIGN(b) : 0);
else return si; /* b is zero */
}
else { /* b and i are of same sign */
- e = EXP(b); /* 2^(e-1) <= b < 2^e */
- if (e>f+mp_bits_per_limb) return si;
+ e = MPFR_EXP(b); /* 2^(e-1) <= b < 2^e */
+ if (e>f+BITS_PER_MP_LIMB) return si;
c = (mp_limb_t) ((i<0) ? -i : i);
count_leading_zeros(k, c);
- k = f+mp_bits_per_limb - k; /* 2^(k-1) <= i*2^f < 2^k */
+ k = f+BITS_PER_MP_LIMB - k; /* 2^(k-1) <= i*2^f < 2^k */
if (k!=e) return (si*(e-k));
/* now k=e */
- c <<= (f+mp_bits_per_limb-k);
- bn = (PREC(b)-1)/mp_bits_per_limb;
- bp = MANT(b) + bn;
+ c <<= (f+BITS_PER_MP_LIMB-k);
+ bn = (MPFR_PREC(b)-1)/BITS_PER_MP_LIMB;
+ bp = MPFR_MANT(b) + bn;
if (*bp>c) return si;
else if (*bp<c) return -si;
diff --git a/mpfr/cputime.h b/mpfr/cputime.h
new file mode 100644
index 000000000..69d49620f
--- /dev/null
+++ b/mpfr/cputime.h
@@ -0,0 +1,25 @@
+/* Return user CPU time measured in milliseconds. Thanks to Torbjorn. */
+
+int cputime _PROTO((void));
+
+#if defined (ANSIONLY) || defined (USG) || defined (__SVR4) || defined (_UNICOS) || defined(__hpux)
+#include <time.h>
+
+int
+cputime ()
+{
+ return (int) ((double) clock () * 1000 / CLOCKS_PER_SEC);
+}
+#else
+#include <sys/types.h>
+#include <sys/resource.h>
+
+int
+cputime ()
+{
+ struct rusage rus;
+
+ getrusage (0, &rus);
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
+}
+#endif
diff --git a/mpfr/div.c b/mpfr/div.c
index ee1475694..bf5ffc371 100644
--- a/mpfr/div.c
+++ b/mpfr/div.c
@@ -1,6 +1,6 @@
/* mpfr_div -- divide two floating-point numbers
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -19,53 +19,91 @@ along with the MPFR Library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
-#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gmp.h"
#include "gmp-impl.h"
-#include "mpfr.h"
#include "longlong.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
/* #define DEBUG */
void
-mpfr_div (mpfr_ptr r, mpfr_srcptr u, mpfr_srcptr v, unsigned char rnd_mode)
+#if __STDC__
+mpfr_div (mpfr_ptr r, mpfr_srcptr u, mpfr_srcptr v, mp_rnd_t rnd_mode)
+#else
+mpfr_div (r, u, v, rnd_mode)
+ mpfr_ptr r;
+ mpfr_srcptr u;
+ mpfr_srcptr v;
+ mp_rnd_t rnd_mode;
+#endif
{
mp_srcptr up, vp;
- mp_ptr rp, tp, tp0, tmp;
- mp_size_t usize, vsize, rrsize;
+ mp_ptr rp, tp, tp0, tmp, tmp2;
+ mp_size_t usize, vsize, rrsize, oldrrsize;
mp_size_t rsize;
mp_size_t sign_quotient;
mp_size_t prec, err;
mp_limb_t q_limb;
mp_exp_t rexp;
- long k, mult, vn;
+ long k, mult, vn, t;
unsigned long cc = 0, rw, nw;
char can_round = 0;
TMP_DECL (marker);
- if (FLAG_NAN(u) || FLAG_NAN(v)) { SET_NAN(r); return; }
-
- usize = (PREC(u) - 1)/BITS_PER_MP_LIMB + 1;
- vsize = (PREC(v) - 1)/BITS_PER_MP_LIMB + 1;
- sign_quotient = (SIGN(u) == SIGN(v) ? 1 : -1);
- prec = PREC(r);
+ if (MPFR_IS_NAN(u) || MPFR_IS_NAN(v)) { MPFR_SET_NAN(r); return; }
- if (!NOTZERO(u)) { SET_ZERO(r); return; }
+ MPFR_CLEAR_NAN(r);
- if (!NOTZERO(v))
- vsize = 1 / v->_mp_d[vsize - 1]; /* Gestion des infinis ? */
-
- if (!NOTZERO(v))
- {
- r->_mp_exp = 0;
- MPN_ZERO(r->_mp_d, r->_mp_size);
+ if (MPFR_IS_INF(u))
+ {
+ if (MPFR_IS_INF(v))
+ MPFR_SET_NAN(r);
+ else
+ {
+ MPFR_SET_INF(r);
+ if (MPFR_SIGN(r) != MPFR_SIGN(u) * MPFR_SIGN(v))
+ MPFR_CHANGE_SIGN(r);
+ }
return;
}
+ else
+ if (MPFR_IS_INF(v))
+ {
+ MPFR_CLEAR_INF(r);
+ MPFR_SET_ZERO(r);
+ if (MPFR_SIGN(r) != MPFR_SIGN(u) * MPFR_SIGN(v))
+ MPFR_CHANGE_SIGN(r);
+ return;
+ }
+
+ MPFR_CLEAR_INF(r); /* clear Inf flag */
+
+ usize = (MPFR_PREC(u) - 1)/BITS_PER_MP_LIMB + 1;
+ vsize = (MPFR_PREC(v) - 1)/BITS_PER_MP_LIMB + 1;
+ sign_quotient = ((MPFR_SIGN(u) * MPFR_SIGN(v) > 0) ? 1 : -1);
+ prec = MPFR_PREC(r);
- up = u->_mp_d;
- vp = v->_mp_d;
+
+ if (!MPFR_NOTZERO(v))
+ {
+ if (!MPFR_NOTZERO(u))
+ { MPFR_SET_NAN(r); return; }
+ else
+ {
+ MPFR_SET_INF(r);
+ if (MPFR_SIGN(r) != MPFR_SIGN(v) * MPFR_SIGN(u))
+ MPFR_CHANGE_SIGN(r);
+ return;
+ }
+ }
+
+ if (!MPFR_NOTZERO(u)) { MPFR_SET_ZERO(r); return; }
+
+ up = MPFR_MANT(u);
+ vp = MPFR_MANT(v);
#ifdef DEBUG
printf("Entering division : ");
@@ -85,19 +123,17 @@ mpfr_div (mpfr_ptr r, mpfr_srcptr u, mpfr_srcptr v, unsigned char rnd_mode)
}
else { mult = (mult < 0 ? 1 : 0); }
- rsize = (PREC(r) + 3)/BITS_PER_MP_LIMB + 1;
- rrsize = PREC(r)/BITS_PER_MP_LIMB + 1;
+ rsize = (MPFR_PREC(r) + 3)/BITS_PER_MP_LIMB + 1;
+ rrsize = MPFR_PREC(r)/BITS_PER_MP_LIMB + 1;
/* Three extra bits are needed in order to get the quotient with enough
precision ; take one extra bit for rrsize in order to solve more
easily the problem of rounding to nearest. */
- /* ATTENTION, USIZE DOIT RESTER > A VSIZE !!!!!!!! */
-
do
{
TMP_MARK (marker);
- rexp = u->_mp_exp - v->_mp_exp;
+ rexp = MPFR_EXP(u) - MPFR_EXP(v);
err = rsize*BITS_PER_MP_LIMB;
if (rsize < vsize) { err-=2; }
@@ -108,13 +144,13 @@ mpfr_div (mpfr_ptr r, mpfr_srcptr u, mpfr_srcptr v, unsigned char rnd_mode)
tp0 = (mp_ptr) TMP_ALLOC ((rsize+rrsize) * BYTES_PER_MP_LIMB);
/* fill by zero rrsize low limbs of t */
MPN_ZERO(tp0, rrsize); tp = tp0 + rrsize;
- tmp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
- rp = (mp_ptr) TMP_ALLOC (rrsize * BYTES_PER_MP_LIMB);
+ rp = (mp_ptr) TMP_ALLOC ((rrsize+1) * BYTES_PER_MP_LIMB);
if (vsize >= rsize) {
- MPN_COPY (tmp, vp + vsize - rsize, rsize);
+ tmp = (mp_ptr) vp + vsize - rsize;
}
else {
+ tmp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
MPN_COPY (tmp + rsize - vsize, vp, vsize);
MPN_ZERO (tmp, rsize - vsize);
}
@@ -137,10 +173,15 @@ mpfr_div (mpfr_ptr r, mpfr_srcptr u, mpfr_srcptr v, unsigned char rnd_mode)
printf(".\n");
#endif
- q_limb = (rsize==rrsize) /* use Burnikel-Ziegler algorithm */
- ? mpn_divrem_n (rp, tp0, tmp, rsize)
- : mpn_divrem (rp, 0, tp0, rsize+rrsize, tmp, rsize);
+#if (__GNU_MP_VERSION < 3)
+ q_limb = mpn_divrem (rp, 0, tp0, rsize+rrsize, tmp, rsize);
tp = tp0; /* location of remainder */
+#else /* mpn_tdiv_qr is the preferred division interface in GMP 3 */
+ tmp2 = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
+ mpn_tdiv_qr(rp, tmp2, 0, tp0, rsize+rrsize, tmp, rsize);
+ q_limb = rp[rrsize];
+ tp = tmp2; /* location of remainder */
+#endif
#ifdef DEBUG
printf("The result is : \n");
@@ -156,8 +197,8 @@ mpfr_div (mpfr_ptr r, mpfr_srcptr u, mpfr_srcptr v, unsigned char rnd_mode)
if (q_limb)
{
count_leading_zeros(k, q_limb);
- mpn_rshift(rp, rp, rrsize, BITS_PER_MP_LIMB - k);
- rp[rrsize - 1] |= (q_limb << k);
+ mpn_rshift(rp, rp, rrsize, BITS_PER_MP_LIMB - k);
+ rp[rrsize - 1] |= (q_limb << k);
rexp += BITS_PER_MP_LIMB - k;
}
else
@@ -168,55 +209,72 @@ mpfr_div (mpfr_ptr r, mpfr_srcptr u, mpfr_srcptr v, unsigned char rnd_mode)
}
can_round = (mpfr_can_round_raw(rp, rrsize, sign_quotient, err,
- GMP_RNDN, rnd_mode, PREC(r))
+ GMP_RNDN, rnd_mode, MPFR_PREC(r))
|| (usize == rsize && vsize == rsize &&
mpfr_can_round_raw(rp, rrsize, sign_quotient, err,
- GMP_RNDZ, rnd_mode, PREC(r))));
+ GMP_RNDZ, rnd_mode, MPFR_PREC(r))));
/* If we used all the limbs of both the dividend and the divisor,
then we have the correct RNDZ rounding */
if (!can_round && (rsize < usize || rsize < vsize))
- {
+ {
#ifdef DEBUG
- printf("Increasing the precision.\n");
+ printf("Increasing the precision.\n");
#endif
- printf("#");
- TMP_FREE(marker);
+ TMP_FREE(marker);
+ /* in case we can't round at the first iteration,
+ jump right away to the maximum precision of both
+ operands, to avoid multiple iterations when for
+ example the divisor is 1.0.
+ */
+ if (rsize < usize) rsize = usize - 1;
+ if (rsize < vsize) rsize = vsize - 1;
}
}
while (!can_round && (rsize < usize || rsize < vsize)
- && (rsize++) && (rrsize++));
+ && (rsize++) && (rrsize++));
/* ON PEUT PROBABLEMENT SE DEBROUILLER DES QUE rsize >= vsize */
/* MAIS IL FAUT AJOUTER LE BOUT QUI MANQUE DE usize A rsize */
+ oldrrsize = rrsize;
+ rrsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1;
+
if (can_round)
{
cc = mpfr_round_raw(rp, rp, err, (sign_quotient == -1 ? 1 : 0),
- PREC(r), rnd_mode);
- rrsize = (PREC(r) - 1)/BITS_PER_MP_LIMB + 1;
+ MPFR_PREC(r), rnd_mode);
}
- else
+ else {
/* Use the remainder to find out the correct rounding */
/* Note that at this point the division has been done */
/* EXACTLY. */
if ((rnd_mode == GMP_RNDD && sign_quotient == -1)
|| (rnd_mode == GMP_RNDU && sign_quotient == 1)
|| (rnd_mode == GMP_RNDN))
- {
+ {
/* We cannot round, so that the last bits of the quotient
have to be zero; just look if the remainder is nonzero */
k = rsize - 1;
while (k >= 0) { if (tp[k]) break; k--; }
if (k >= 0)
- cc = mpn_add_1(rp, rp, rrsize, (mp_limb_t)1 << (BITS_PER_MP_LIMB -
- (PREC(r) &
- (BITS_PER_MP_LIMB - 1))));
+ {
+ t = MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1);
+ if (t)
+ {
+ cc = mpn_add_1(rp, rp, rrsize,
+ (mp_limb_t)1 << (BITS_PER_MP_LIMB - t));
+ }
+ else
+ {
+ cc = mpn_add_1(rp, rp, rrsize, 1);
+ }
+ }
else
if (rnd_mode == GMP_RNDN) /* even rounding */
{
- rw = (PREC(r) + 1) & (BITS_PER_MP_LIMB - 1);
+ rw = (MPFR_PREC(r) + 1) & (BITS_PER_MP_LIMB - 1);
if (rw) { rw = BITS_PER_MP_LIMB - rw; nw = 0; } else nw = 1;
if ((rw ? (rp[nw] >> (rw + 1)) & 1 :
(rp[nw] >> (BITS_PER_MP_LIMB - 1)) & 1))
@@ -227,21 +285,26 @@ mpfr_div (mpfr_ptr r, mpfr_srcptr u, mpfr_srcptr v, unsigned char rnd_mode)
}
/* cas 0111111 */
}
+ /* Warning: we computed the result on oldrrsize limbs, but we want it
+ on rrsize limbs only. Both can differ, especially when the target
+ precision is a multiple of the number of bits per limb, since we've
+ taken an extra bit to make rounding to nearest easier. */
+ rp += oldrrsize-rrsize;
+ }
+
+
+ if (sign_quotient * MPFR_SIGN(r) < 0) { MPFR_CHANGE_SIGN(r); }
+ MPFR_EXP(r) = rexp;
- if (sign_quotient != SIGN(r)) { CHANGE_SIGN(r); }
- r->_mp_exp = rexp;
-
if (cc) {
mpn_rshift(rp, rp, rrsize, 1);
rp[rrsize-1] |= (mp_limb_t) 1 << (BITS_PER_MP_LIMB-1);
- r->_mp_exp++;
+ MPFR_EXP(r)++;
}
- rsize = rrsize;
- rrsize = (PREC(r) - 1)/BITS_PER_MP_LIMB + 1;
- MPN_COPY(r->_mp_d, rp + rsize - rrsize, rrsize);
- MANT(r) [0] &= ~(((mp_limb_t)1 << (BITS_PER_MP_LIMB -
- (PREC(r) & (BITS_PER_MP_LIMB - 1)))) - 1) ;
-
+ rw = rrsize * BITS_PER_MP_LIMB - MPFR_PREC(r);
+ MPN_COPY(MPFR_MANT(r), rp, rrsize);
+ MPFR_MANT(r)[0] &= ~(((mp_limb_t)1 << rw) - 1);
+
TMP_FREE (marker);
}
diff --git a/mpfr/div_2exp.c b/mpfr/div_2exp.c
index e7602db44..e518f6518 100644
--- a/mpfr/div_2exp.c
+++ b/mpfr/div_2exp.c
@@ -1,6 +1,6 @@
/* mpfr_div_2exp -- divide a floating-point number by a power of two
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -23,21 +23,22 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
void
#if __STDC__
-mpfr_div_2exp(mpfr_ptr y, mpfr_srcptr x, unsigned long int n, unsigned char rnd_mode)
+mpfr_div_2exp (mpfr_ptr y, mpfr_srcptr x, unsigned long int n, mp_rnd_t rnd_mode)
#else
-mpfr_div_2exp(y, x, n, rnd_mode)
+mpfr_div_2exp (y, x, n, rnd_mode)
mpfr_ptr y;
- mpfr_srcptr x;
- unsigned long int n;
- unsigned char rnd_mode;
+ mpfr_srcptr x;
+ unsigned long int n;
+ mp_rnd_t rnd_mode;
#endif
{
/* Important particular case */
if (y != x) mpfr_set(y, x, rnd_mode);
- EXP(y) -= n;
+ MPFR_EXP(y) -= n;
return;
}
diff --git a/mpfr/div_ui.c b/mpfr/div_ui.c
index 7cd124142..bf5e94c05 100644
--- a/mpfr/div_ui.c
+++ b/mpfr/div_ui.c
@@ -1,6 +1,6 @@
/* mpfr_div_ui -- divide a floating-point number by a machine integer
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -22,37 +22,60 @@ MA 02111-1307, USA. */
#include <stdio.h>
#include "gmp.h"
#include "gmp-impl.h"
-#include "longlong.h"
+#include "longlong.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
/* #define DEBUG */
/* returns 0 if result exact, non-zero otherwise */
int
#ifdef __STDC__
-mpfr_div_ui(mpfr_ptr y, mpfr_srcptr x, unsigned long u, unsigned char rnd_mode)
+mpfr_div_ui(mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mp_rnd_t rnd_mode)
#else
mpfr_div_ui(y, x, u, rnd_mode)
- mpfr_ptr y;
+ mpfr_ptr y;
mpfr_srcptr x;
- unsigned long u;
- unsigned char rnd_mode;
+ unsigned long int u;
+ mp_rnd_t rnd_mode;
#endif
{
int xn, yn, dif, sh, i; mp_limb_t *xp, *yp, *tmp, c, d;
TMP_DECL(marker);
- if (FLAG_NAN(x)) { SET_NAN(y); return 1; }
- if (u==0) { printf("infinity\n"); return 1; }
+ if (MPFR_IS_NAN(x)) { MPFR_SET_NAN(y); return 1; }
+
+ MPFR_CLEAR_NAN(y); /* clear NaN flag */
+
+ if (MPFR_IS_INF(x))
+ {
+ MPFR_SET_INF(y);
+ if (MPFR_SIGN(y) * MPFR_SIGN(x) < 0) /* consider u=0 as +0 */
+ MPFR_CHANGE_SIGN(y);
+ return 0;
+ /* TODO: semantique de la division par un zero entier ? signe ? */
+ }
+
+ if (u==0)
+ {
+ if (MPFR_IS_ZERO(x)) { MPFR_SET_NAN(y) ; return 1; }
+ else
+ {
+ MPFR_SET_INF(y); MPFR_SET_SAME_SIGN(y, x); return 0;
+ /* TODO: semantique de la division dans ce cas-la aussi ? */
+ }
+ }
+
+ MPFR_CLEAR_INF(y);
TMP_MARK(marker);
- xn = (PREC(x)-1)/BITS_PER_MP_LIMB + 1;
- yn = (PREC(y)-1)/BITS_PER_MP_LIMB + 1;
+ xn = (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB + 1;
+ yn = (MPFR_PREC(y)-1)/BITS_PER_MP_LIMB + 1;
- xp = MANT(x);
- yp = MANT(y);
- EXP(y) = EXP(x);
- if (SIGN(x)!=SIGN(y)) CHANGE_SIGN(y);
+ xp = MPFR_MANT(x);
+ yp = MPFR_MANT(y);
+ MPFR_EXP(y) = MPFR_EXP(x);
+ if (MPFR_SIGN(x) * MPFR_SIGN(y) < 0) MPFR_CHANGE_SIGN(y);
dif = yn+1-xn;
#ifdef DEBUG
@@ -61,36 +84,36 @@ mpfr_div_ui(y, x, u, rnd_mode)
#endif
/* we need to store yn+1 = xn + dif limbs of the quotient */
- if (ABSSIZE(y)>=yn+1) tmp=yp;
- else tmp=TMP_ALLOC((yn+1)*BYTES_PER_MP_LIMB);
+ /* don't use tmp=yp since the mpn_lshift call below requires yp >= tmp+1 */
+ tmp=TMP_ALLOC((yn+1)*BYTES_PER_MP_LIMB);
c = (mp_limb_t) u;
if (dif>=0) {
- /* patch for bug in mpn_divrem_1 */
-#if (UDIV_NEEDS_NORMALIZATION==1)
+#if (__GNU_MP_VERSION < 3) && (UDIV_NEEDS_NORMALIZATION==1)
+ /* patch for bug in mpn_divrem_1 for GMP 2.xxx */
count_leading_zeros(sh, c);
c <<= sh;
- EXP(y) += sh;
+ MPFR_EXP(y) += sh;
#endif
c = mpn_divrem_1(tmp, dif, xp, xn, c);
}
else /* dif < 0 i.e. xn > yn */
c = mpn_divrem_1(tmp, 0, xp-dif, yn, c);
- if (tmp[yn]==0) { tmp--; sh=0; EXP(y) -= mp_bits_per_limb; }
+ if (tmp[yn]==0) { tmp--; sh=0; MPFR_EXP(y) -= BITS_PER_MP_LIMB; }
/* shift left to normalize */
count_leading_zeros(sh, tmp[yn]);
if (sh) {
mpn_lshift(yp, tmp+1, yn, sh);
yp[0] += tmp[0] >> (BITS_PER_MP_LIMB-sh);
- EXP(y) -= sh;
+ MPFR_EXP(y) -= sh;
}
else MPN_COPY(yp, tmp+1, yn);
#ifdef DEBUG
-printf("y="); mpfr_print_raw(y); putchar('\n');
+ printf("y="); mpfr_print_raw(y); putchar('\n');
#endif
- sh = yn*BITS_PER_MP_LIMB - PREC(y);
+ sh = yn*BITS_PER_MP_LIMB - MPFR_PREC(y);
/* it remains sh bits in less significant limb of y */
d = *yp & (((mp_limb_t)1 << sh) - 1);
@@ -106,10 +129,10 @@ printf("y="); mpfr_print_raw(y); putchar('\n');
case GMP_RNDZ:
return 1; /* result is inexact */
case GMP_RNDU:
- if (SIGN(y)>0) mpfr_add_one_ulp(y);
+ if (MPFR_SIGN(y)>0) mpfr_add_one_ulp(y);
return 1; /* result is inexact */
case GMP_RNDD:
- if (SIGN(y)<0) mpfr_add_one_ulp(y);
+ if (MPFR_SIGN(y)<0) mpfr_add_one_ulp(y);
return 1; /* result is inexact */
case GMP_RNDN:
if (d < ((mp_limb_t)1 << (sh-1))) return 1;
diff --git a/mpfr/dump.c b/mpfr/dump.c
new file mode 100644
index 000000000..a0319c015
--- /dev/null
+++ b/mpfr/dump.c
@@ -0,0 +1,63 @@
+/* mpfr_dump -- Dump a float to stdout.
+
+ THIS IS AN INTERNAL FUNCTION WITH A MUTABLE INTERFACE. IT IS NOT SAFE TO
+ CALL THIS FUNCTION DIRECTLY. IN FACT, IT IS ALMOST GUARANTEED THAT THIS
+ FUNCTION WILL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
+
+
+Copyright (C) 1993, 1994, 1995, 2000 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <strings.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+void
+#if __STDC__
+mpfr_dump (mpfr_srcptr u, mp_rnd_t rnd_mode)
+#else
+mpfr_dump (u, rnd_mode)
+ mpfr_srcptr u;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ mp_exp_t exp;
+ char *str;
+
+ if (MPFR_IS_INF(u))
+ {
+ if (MPFR_SIGN(u) == 1) printf("Inf\n"); else printf("-Inf\n");
+ return;
+ }
+ if (MPFR_IS_NAN(u))
+ {
+ printf("NaN\n");
+ return;
+ }
+
+ str = mpfr_get_str (NULL, &exp, 10, 0, u, rnd_mode);
+ if (str[0] == '-')
+ printf ("-0.%se%ld\n", str + 1, exp);
+ else
+ printf ("0.%se%ld\n", str, exp);
+ (*_mp_free_func) (str, strlen(str)+1);
+}
diff --git a/mpfr/eq.c b/mpfr/eq.c
new file mode 100644
index 000000000..95b04a986
--- /dev/null
+++ b/mpfr/eq.c
@@ -0,0 +1,135 @@
+/* mpfr_eq -- Compare two floats up to a specified bit #.
+
+Copied from mpf_eq.
+
+Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+int
+#if __STDC__
+mpfr_eq (mpfr_srcptr u, mpfr_srcptr v, unsigned long int n_bits)
+#else
+mpfr_eq (u, v, n_bits)
+ mpfr_srcptr u;
+ mpfr_srcptr v;
+ unsigned long int n_bits;
+#endif
+{
+ mp_srcptr up, vp;
+ mp_size_t usize, vsize, size, i;
+ mp_exp_t uexp, vexp;
+ int usign, k;
+
+ uexp = MPFR_EXP(u);
+ vexp = MPFR_EXP(v);
+
+ usize = (MPFR_PREC(u)-1)/BITS_PER_MP_LIMB + 1;
+ vsize = (MPFR_PREC(v)-1)/BITS_PER_MP_LIMB + 1;
+
+ usign = MPFR_SIGN(u);
+
+ /* 1. Are the signs different? */
+ if (usign == MPFR_SIGN(v))
+ {
+ /* U and V are both non-negative or both negative. */
+ if (!MPFR_NOTZERO(u))
+ return !MPFR_NOTZERO(v);
+ if (!MPFR_NOTZERO(v))
+ return !MPFR_NOTZERO(u);
+
+ /* Fall out. */
+ }
+ else
+ {
+ /* Either U or V is negative, but not both. */
+ if (MPFR_NOTZERO(u) || MPFR_NOTZERO(v))
+ return 0;
+ else return 1; /* particular case -0 = +0 */
+ }
+
+ /* U and V have the same sign and are both non-zero. */
+ if (MPFR_IS_INF(u))
+ return (MPFR_IS_INF(v) && (usign == MPFR_SIGN(v)));
+ else if (MPFR_IS_INF(v)) return 0;
+
+ if (MPFR_IS_NAN(u) || MPFR_IS_NAN(v)) return 0;
+
+ /* 2. Are the exponents different? */
+ if (uexp > vexp)
+ return 0; /* ??? handle (uexp = vexp + 1) */
+ if (vexp > uexp)
+ return 0; /* ??? handle (vexp = uexp + 1) */
+
+ usize = ABS (usize);
+ vsize = ABS (vsize);
+
+ up = MPFR_MANT(u);
+ vp = MPFR_MANT(v);
+
+ if (usize > vsize)
+ {
+ if (vsize * BITS_PER_MP_LIMB < n_bits)
+ {
+ k = usize - vsize - 1;
+ while (k >= 0 && !up[k]) --k;
+ if (k >= 0)
+ return 0; /* surely too different */
+ }
+ size = vsize;
+ }
+ else if (vsize > usize)
+ {
+ if (usize * BITS_PER_MP_LIMB < n_bits)
+ {
+ k = vsize - usize - 1;
+ while (k >= 0 && !vp[k]) --k;
+ if (k >= 0)
+ return 0; /* surely too different */
+ }
+ size = usize;
+ }
+ else
+ {
+ size = usize;
+ }
+
+ if (size > (n_bits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB)
+ size = (n_bits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB;
+
+ up += usize - size;
+ vp += vsize - size;
+
+ for (i = size - 1; i > 0; i--)
+ {
+ if (up[i] != vp[i])
+ return 0;
+ }
+
+ if (n_bits & (BITS_PER_MP_LIMB - 1))
+ return (up[i] >> (BITS_PER_MP_LIMB - (n_bits & (BITS_PER_MP_LIMB - 1))) ==
+ vp[i] >> (BITS_PER_MP_LIMB - (n_bits & (BITS_PER_MP_LIMB - 1))));
+ else
+ return (up[i] == vp[i]);
+}
diff --git a/mpfr/exp.c b/mpfr/exp.c
index c3ec218a0..4dfb614c3 100644
--- a/mpfr/exp.c
+++ b/mpfr/exp.c
@@ -1,6 +1,6 @@
/* mpfr_exp -- exponential of a floating-point number
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -20,14 +20,16 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include <stdio.h>
-#include <math.h>
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
/* #define DEBUG */
-#define LOG2 0.69314718055994528622 /* log(2) rounded to zero on 53 bits */
+extern int mpfr_exp2 _PROTO((mpfr_ptr, mpfr_srcptr, mp_rnd_t));
+extern int mpfr_exp3 _PROTO((mpfr_ptr, mpfr_srcptr, mp_rnd_t));
+
/* use Brent's formula exp(x) = (1+r+r^2/2!+r^3/3!+...)^(2^K)*2^n
where x = n*log(2)+(2^K)*r
@@ -35,142 +37,58 @@ MA 02111-1307, USA. */
*/
int
#if __STDC__
-mpfr_exp(mpfr_ptr y, mpfr_srcptr x, unsigned char rnd_mode)
+mpfr_exp (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
#else
-mpfr_exp(y, x, rnd_mode)
- mpfr_ptr y;
- mpfr_srcptr x;
- unsigned char rnd_mode;
+mpfr_exp (y, x, rnd_mode)
+ mpfr_ptr y;
+ mpfr_srcptr x;
+ mp_rnd_t rnd_mode;
#endif
{
- int n, expx, K, precy, q, k, l, expr, err;
- mpfr_t r, s, t;
-
- if (FLAG_NAN(x)) { SET_NAN(y); return 1; }
- if (!NOTZERO(x)) { mpfr_set_ui(y, 1, GMP_RNDN); return 0; }
-
- expx = EXP(x);
- precy = PREC(y);
-#ifdef DEBUG
- printf("EXP(x)=%d\n",expx);
-#endif
+ int expx, precy;
+
+ if (MPFR_IS_NAN(x)) { MPFR_SET_NAN(y); return 1; }
+
+ MPFR_CLEAR_NAN(y);
+
+ if (MPFR_IS_INF(x))
+ {
+ if (MPFR_SIGN(x) > 0) {
+ MPFR_SET_INF(y);
+ if (MPFR_SIGN(y) < 0) MPFR_CHANGE_SIGN(y);
+ }
+ else {
+ MPFR_CLEAR_INF(y);
+ MPFR_SET_ZERO(y);
+ if (MPFR_SIGN(y) < 0) MPFR_CHANGE_SIGN(y);
+ }
+ /* TODO: conflits entre infinis et zeros ? */
+ return 1;
+ }
+
+ MPFR_CLEAR_INF(y);
+
+ if (!MPFR_NOTZERO(x)) { mpfr_set_ui(y, 1, GMP_RNDN); return 0; }
+
+ expx = MPFR_EXP(x);
+ precy = MPFR_PREC(y);
/* if x > (2^31-1)*ln(2), then exp(x) > 2^(2^31-1) i.e. gives +infinity */
if (expx > 30) {
- if (SIGN(x)>0) { printf("+infinity"); return 1; }
- else { SET_ZERO(y); return 1; }
+ if (MPFR_SIGN(x)>0) { printf("+infinity"); return 1; }
+ else { MPFR_SET_ZERO(y); return 1; }
}
/* if x < 2^(-precy), then exp(x) i.e. gives 1 +/- 1 ulp(1) */
- if (expx < -precy) { int signx = SIGN(x);
+ if (expx < -precy) { int signx = MPFR_SIGN(x);
mpfr_set_ui(y, 1, rnd_mode);
if (signx>0 && rnd_mode==GMP_RNDU) mpfr_add_one_ulp(y);
else if (signx<0 && (rnd_mode==GMP_RNDD || rnd_mode==GMP_RNDZ))
mpfr_sub_one_ulp(y);
return 1; }
- n = (int) floor(mpfr_get_d(x)/LOG2);
-
- K = (int) sqrt( (double) precy );
- l = (precy-1)/K + 1;
- err = K + (int) ceil(log(2.0*(double)l+18.0)/LOG2);
- /* add K extra bits, i.e. failure probability <= 1/2^K = O(1/precy) */
- q = precy + err + K + 3;
- mpfr_init2(r, q); mpfr_init2(s, q); mpfr_init2(t, q);
- /* the algorithm consists in computing an upper bound of exp(x) using
- a precision of q bits, and see if we can round to PREC(y) taking
- into account the maximal error. Otherwise we increase q. */
- do {
-#ifdef DEBUG
- printf("n=%d K=%d l=%d q=%d\n",n,K,l,q);
-#endif
-
- /* if n<0, we have to get an upper bound of log(2)
- in order to get an upper bound of r = x-n*log(2) */
- mpfr_log2(s, (n>=0) ? GMP_RNDZ : GMP_RNDU);
-#ifdef DEBUG
- printf("n=%d log(2)=",n); mpfr_print_raw(s); putchar('\n');
-#endif
- mpfr_mul_ui(r, s, (n<0) ? -n : n, (n>=0) ? GMP_RNDZ : GMP_RNDU);
- if (n<0) mpfr_neg(r, r, GMP_RNDD);
- /* r = floor(n*log(2)) */
-
-#ifdef DEBUG
- printf("x=%1.20e\n",mpfr_get_d(x));
- printf(" ="); mpfr_print_raw(x); putchar('\n');
- printf("r=%1.20e\n",mpfr_get_d(r));
- printf(" ="); mpfr_print_raw(r); putchar('\n');
-#endif
- mpfr_sub(r, x, r, GMP_RNDU);
- if (SIGN(r)<0) { /* initial approximation n was too large */
- n--;
- mpfr_mul_ui(r, s, (n<0) ? -n : n, GMP_RNDZ);
- if (n<0) mpfr_neg(r, r, GMP_RNDD);
- mpfr_sub(r, x, r, GMP_RNDU);
- }
-#ifdef DEBUG
- printf("x-r=%1.20e\n",mpfr_get_d(r));
- printf(" ="); mpfr_print_raw(r); putchar('\n');
- if (SIGN(r)<0) { fprintf(stderr,"Error in mpfr_exp: r<0\n"); exit(1); }
-#endif
- mpfr_div_2exp(r, r, K, GMP_RNDU); /* r = (x-n*log(2))/2^K */
- mpfr_set_ui(s, 1, GMP_RNDU);
- mpfr_set_ui(t, 1, GMP_RNDU);
-
- l = 1; expr = EXP(r);
- do {
- mpfr_mul(t, t, r, GMP_RNDU);
- mpfr_div_ui(t, t, l, GMP_RNDU);
- mpfr_add(s, s, t, GMP_RNDU);
-#ifdef DEBUG
- printf("l=%d t=%1.20e\n",l,mpfr_get_d(t));
- printf("s=%1.20e\n",mpfr_get_d(s));
-#endif
- l++;
- } while (EXP(t)+expr > -q);
-#ifdef DEBUG
- printf("l=%d q=%d (K+l)*q^2=%1.3e\n", l, q, (K+l)*(double)q*q);
-#endif
-
- /* add 2 ulp to take into account rest of summation */
- mpfr_add_one_ulp(s);
- mpfr_add_one_ulp(s);
-
- for (k=0;k<K;k++) {
- mpfr_mul(s, s, s, GMP_RNDU);
-#ifdef DEBUG
- printf("k=%d s=%1.20e\n",k,mpfr_get_d(s));
-#endif
- }
-
- if (n>0) mpfr_mul_2exp(s, s, n, GMP_RNDU);
- else mpfr_div_2exp(s, s, -n, GMP_RNDU);
-
- /* error is at most 2^K*(2l+18) ulp */
- l = 2*l+17; k=0; while (l) { k++; l >>= 1; }
- /* now k = ceil(log(2l+18)/log(2)) */
- K += k;
-#ifdef DEBUG
- printf("after mult. by 2^n:\n");
- if (EXP(s)>-1024) printf("s=%1.20e\n",mpfr_get_d(s));
- printf(" ="); mpfr_print_raw(s); putchar('\n');
- printf("err=%d bits\n", K);
-#endif
-
- l = mpfr_can_round(s, q-K, GMP_RNDU, rnd_mode, precy);
- if (l==0) {
-#ifdef DEBUG
- printf("not enough precision, use %d\n", q+BITS_PER_MP_LIMB);
- printf("q=%d q-K=%d precy=%d\n",q,q-K,precy);
-#endif
- q += BITS_PER_MP_LIMB;
- mpfr_set_prec(r, q); mpfr_set_prec(s, q); mpfr_set_prec(t, q);
- }
- } while (l==0);
-
- mpfr_set(y, s, rnd_mode);
-
- mpfr_clear(r); mpfr_clear(s); mpfr_clear(t);
+ if (precy > 13000) mpfr_exp3(y, x, rnd_mode); /* O(M(n) log(n)^2) */
+ else mpfr_exp2(y, x, rnd_mode); /* O(n^(1/3) M(n)) */
return 1;
}
diff --git a/mpfr/exp2.c b/mpfr/exp2.c
new file mode 100644
index 000000000..d18926dc4
--- /dev/null
+++ b/mpfr/exp2.c
@@ -0,0 +1,431 @@
+/* mpfr_exp2 -- exponential of a floating-point number
+ using Brent's algorithms in O(n^(1/2)*M(n)) and O(n^(1/3)*M(n))
+
+Copyright (C) 1999-2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+int mpfr_exp2_aux (mpz_t, mpfr_srcptr, int, int*);
+int mpfr_exp2_aux2 (mpz_t, mpfr_srcptr, int, int*);
+mp_exp_t mpz_normalize (mpz_t, mpz_t, int);
+int mpz_normalize2 (mpz_t, mpz_t, int, int);
+int mpfr_exp2 (mpfr_ptr, mpfr_srcptr, mp_rnd_t);
+
+/* returns floor(sqrt(n)) */
+unsigned long _mpfr_isqrt (unsigned long n)
+{
+ unsigned long s;
+
+ s = 1;
+ do {
+ s = (s + n / s) / 2;
+ } while (!(s*s <= n && n <= s*(s+2)));
+ return s;
+}
+
+/* returns floor(n^(1/3)) */
+unsigned long _mpfr_cuberoot (unsigned long n)
+{
+ double s, is;
+
+ s = 1.0;
+ do {
+ s = (2*s*s*s + (double) n) / (3*s*s);
+ is = (double) ((int) s);
+ } while (!(is*is*is <= (double) n && (double) n < (is+1)*(is+1)*(is+1)));
+ return (unsigned long) is;
+}
+
+#define SWITCH 100 /* number of bits to switch from O(n^(1/2)*M(n)) method
+ to O(n^(1/3)*M(n)) method */
+
+#define MY_INIT_MPZ(x, s) { \
+ (x)->_mp_alloc = (s); \
+ PTR(x) = (mp_ptr) TMP_ALLOC((s)*BYTES_PER_MP_LIMB); \
+ (x)->_mp_size = 0; }
+
+/* #define DEBUG */
+
+/* if k = the number of bits of z > q, divides z by 2^(k-q) and returns k-q.
+ Otherwise do nothing and return 0.
+ */
+mp_exp_t
+#if __STDC__
+mpz_normalize (mpz_t rop, mpz_t z, int q)
+#else
+mpz_normalize (rop, z, q)
+ mpz_t rop;
+ mpz_t z;
+ int q;
+#endif
+{
+ int k;
+
+ k = mpz_sizeinbase(z, 2);
+ if (k > q) {
+ mpz_div_2exp(rop, z, k-q);
+ return k-q;
+ }
+ else {
+ if (rop != z) mpz_set(rop, z);
+ return 0;
+ }
+}
+
+/* if expz > target, shift z by (expz-target) bits to the left.
+ if expz < target, shift z by (target-expz) bits to the right.
+ Returns target.
+*/
+int
+#if __STDC__
+mpz_normalize2 (mpz_t rop, mpz_t z, int expz, int target)
+#else
+mpz_normalize2 (rop, z, expz, target)
+ mpz_t rop;
+ mpz_t z;
+ int expz;
+ int target;
+#endif
+{
+ if (target > expz) mpz_div_2exp(rop, z, target-expz);
+ else mpz_mul_2exp(rop, z, expz-target);
+ return target;
+}
+
+/* use Brent's formula exp(x) = (1+r+r^2/2!+r^3/3!+...)^(2^K)*2^n
+ where x = n*log(2)+(2^K)*r
+ together with Brent-Kung O(t^(1/2)) algorithm for the evaluation of
+ power series. The resulting complexity is O(n^(1/3)*M(n)).
+*/
+int
+#if __STDC__
+mpfr_exp2 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
+#else
+mpfr_exp2 (y, x, rnd_mode)
+ mpfr_ptr y;
+ mpfr_srcptr x;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ int n, expx, K, precy, q, k, l, err, exps;
+ mpfr_t r, s, t; mpz_t ss;
+ TMP_DECL(marker);
+
+ if (MPFR_IS_NAN(x)) { MPFR_SET_NAN(y); return 1; }
+ if (MPFR_IS_INF(x))
+ {
+ if (MPFR_SIGN(x) > 0)
+ { MPFR_SET_INF(y); if (MPFR_SIGN(y) == -1) { MPFR_CHANGE_SIGN(y); } }
+ else
+ { MPFR_SET_ZERO(y); if (MPFR_SIGN(y) == -1) { MPFR_CHANGE_SIGN(y); } }
+ /* TODO: conflits entre infinis et zeros ? */
+ }
+ if (!MPFR_NOTZERO(x)) { mpfr_set_ui(y, 1, GMP_RNDN); return 0; }
+
+ expx = MPFR_EXP(x);
+ precy = MPFR_PREC(y);
+#ifdef DEBUG
+ printf("MPFR_EXP(x)=%d\n",expx);
+#endif
+
+ /* if x > (2^31-1)*ln(2), then exp(x) > 2^(2^31-1) i.e. gives +infinity */
+ if (expx > 30) {
+ if (MPFR_SIGN(x) > 0) {
+ MPFR_SET_INF(y);
+ if (MPFR_SIGN(y) < 0) MPFR_CHANGE_SIGN(y);
+ return 1;
+ }
+ else { MPFR_SET_ZERO(y); return 1; }
+ }
+
+ /* if x < 2^(-precy), then exp(x) i.e. gives 1 +/- 1 ulp(1) */
+ if (expx < -precy) { int signx = MPFR_SIGN(x);
+ mpfr_set_ui(y, 1, rnd_mode);
+ if (signx>0 && rnd_mode==GMP_RNDU) mpfr_add_one_ulp(y);
+ else if (signx<0 && (rnd_mode==GMP_RNDD || rnd_mode==GMP_RNDZ))
+ mpfr_sub_one_ulp(y);
+ return 1; }
+
+ n = (int) (mpfr_get_d(x) / LOG2);
+
+ /* for the O(n^(1/2)*M(n)) method, the Taylor series computation of
+ n/K terms costs about n/(2K) multiplications when computed in fixed
+ point */
+ K = (precy<SWITCH) ? _mpfr_isqrt((precy + 1) / 2) : _mpfr_cuberoot (4*precy);
+ l = (precy-1)/K + 1;
+ err = K + (int) _mpfr_ceil_log2 (2.0 * (double) l + 18.0);
+ /* add K extra bits, i.e. failure probability <= 1/2^K = O(1/precy) */
+ q = precy + err + K + 3;
+ mpfr_init2(r, q); mpfr_init2(s, q); mpfr_init2(t, q);
+ /* the algorithm consists in computing an upper bound of exp(x) using
+ a precision of q bits, and see if we can round to MPFR_PREC(y) taking
+ into account the maximal error. Otherwise we increase q. */
+ do {
+#ifdef DEBUG
+ printf("n=%d K=%d l=%d q=%d\n",n,K,l,q);
+#endif
+
+ /* if n<0, we have to get an upper bound of log(2)
+ in order to get an upper bound of r = x-n*log(2) */
+ mpfr_const_log2 (s, (n>=0) ? GMP_RNDZ : GMP_RNDU);
+#ifdef DEBUG
+ printf("n=%d log(2)=",n); mpfr_print_raw(s); putchar('\n');
+#endif
+ mpfr_mul_ui(r, s, (n<0) ? -n : n, (n>=0) ? GMP_RNDZ : GMP_RNDU);
+ if (n<0) mpfr_neg(r, r, GMP_RNDD);
+ /* r = floor(n*log(2)) */
+
+#ifdef DEBUG
+ printf("x=%1.20e\n",mpfr_get_d(x));
+ printf(" ="); mpfr_print_raw(x); putchar('\n');
+ printf("r=%1.20e\n",mpfr_get_d(r));
+ printf(" ="); mpfr_print_raw(r); putchar('\n');
+#endif
+ mpfr_sub(r, x, r, GMP_RNDU);
+ if (MPFR_SIGN(r)<0) { /* initial approximation n was too large */
+ n--;
+ mpfr_mul_ui(r, s, (n<0) ? -n : n, GMP_RNDZ);
+ if (n<0) mpfr_neg(r, r, GMP_RNDD);
+ mpfr_sub(r, x, r, GMP_RNDU);
+ }
+#ifdef DEBUG
+ printf("x-r=%1.20e\n",mpfr_get_d(r));
+ printf(" ="); mpfr_print_raw(r); putchar('\n');
+ if (MPFR_SIGN(r)<0) { fprintf(stderr,"Error in mpfr_exp: r<0\n"); exit(1); }
+#endif
+ mpfr_div_2exp(r, r, K, GMP_RNDU); /* r = (x-n*log(2))/2^K */
+
+ TMP_MARK(marker);
+ MY_INIT_MPZ(ss, 3 + 2*((q-1)/BITS_PER_MP_LIMB));
+ exps = mpz_set_fr(ss, s);
+ /* s <- 1 + r/1! + r^2/2! + ... + r^l/l! */
+ l = (precy<SWITCH) ? mpfr_exp2_aux(ss, r, q, &exps) /* naive method */
+ : mpfr_exp2_aux2(ss, r, q, &exps); /* Brent/Kung method */
+
+#ifdef DEBUG
+ printf("l=%d q=%d (K+l)*q^2=%1.3e\n", l, q, (K+l)*(double)q*q);
+#endif
+
+ for (k=0;k<K;k++) {
+ mpz_mul(ss, ss, ss); exps <<= 1;
+ exps += mpz_normalize(ss, ss, q);
+ }
+ mpfr_set_z(s, ss, GMP_RNDN); MPFR_EXP(s) += exps;
+
+ if (n>0) mpfr_mul_2exp(s, s, n, GMP_RNDU);
+ else mpfr_div_2exp(s, s, -n, GMP_RNDU);
+
+ /* error is at most 2^K*(3l*(l+1)) ulp for mpfr_exp2_aux */
+ if (precy<SWITCH) l = 3*l*(l+1);
+ else l = l*(l+4);
+ k=0; while (l) { k++; l >>= 1; }
+ /* now k = ceil(log(error in ulps)/log(2)) */
+ K += k;
+#ifdef DEBUG
+ printf("after mult. by 2^n:\n");
+ if (MPFR_EXP(s)>-1024) printf("s=%1.20e\n",mpfr_get_d(s));
+ printf(" ="); mpfr_print_raw(s); putchar('\n');
+ printf("err=%d bits\n", K);
+#endif
+
+ l = mpfr_can_round(s, q-K, GMP_RNDN, rnd_mode, precy);
+ if (l==0) {
+#ifdef DEBUG
+ printf("not enough precision, use %d\n", q+BITS_PER_MP_LIMB);
+ printf("q=%d q-K=%d precy=%d\n",q,q-K,precy);
+#endif
+ q += BITS_PER_MP_LIMB;
+ mpfr_set_prec(r, q); mpfr_set_prec(s, q); mpfr_set_prec(t, q);
+ }
+ } while (l==0);
+
+ mpfr_set(y, s, rnd_mode);
+
+ TMP_FREE(marker);
+ mpfr_clear(r); mpfr_clear(s); mpfr_clear(t);
+ return 1;
+}
+
+/* s <- 1 + r/1! + r^2/2! + ... + r^l/l! while MPFR_EXP(r^l/l!)+MPFR_EXPR(r)>-q
+ using naive method with O(l) multiplications.
+ Return the number of iterations l.
+ The absolute error on s is less than 3*l*(l+1)*2^(-q).
+ Version using fixed-point arithmetic with mpz instead
+ of mpfr for internal computations.
+ s must have at least qn+1 limbs (qn should be enough, but currently fails
+ since mpz_mul_2exp(s, s, q-1) reallocates qn+1 limbs)
+*/
+int
+#if __STDC__
+mpfr_exp2_aux(mpz_t s, mpfr_srcptr r, int q, int *exps)
+#else
+mpfr_exp2_aux(s, r, q, exps)
+ mpz_t s;
+ mpfr_srcptr r;
+ int q;
+ int *exps;
+#endif
+{
+ int l, dif, qn;
+ mpz_t t, rr; mp_exp_t expt, expr;
+ TMP_DECL(marker);
+
+ TMP_MARK(marker);
+ qn = 1 + (q-1)/BITS_PER_MP_LIMB;
+ MY_INIT_MPZ(t, 2*qn+1); /* 2*qn+1 is neeeded since mpz_div_2exp may
+ need an extra limb */
+ MY_INIT_MPZ(rr, qn+1);
+ mpz_set_ui(t, 1); expt=0;
+ mpz_set_ui(s, 1); mpz_mul_2exp(s, s, q-1); *exps = 1-q; /* s = 2^(q-1) */
+ expr = mpz_set_fr(rr, r); /* no error here */
+
+ l = 0;
+ do {
+ l++;
+ mpz_mul(t, t, rr); expt=expt+expr;
+ dif = *exps + mpz_sizeinbase(s, 2) - expt - mpz_sizeinbase(t, 2);
+ /* truncates the bits of t which are < ulp(s) = 2^(1-q) */
+ expt += mpz_normalize(t, t, q-dif); /* error at most 2^(1-q) */
+ mpz_div_ui(t, t, l); /* error at most 2^(1-q) */
+ /* the error wrt t^l/l! is here at most 3*l*ulp(s) */
+#ifdef DEBUG
+ if (expt != *exps) {
+ fprintf(stderr, "Error: expt != exps %d %d\n", expt, *exps); exit(1);
+ }
+#endif
+ mpz_add(s, s, t); /* no error here: exact */
+ /* ensures rr has the same size as t: after several shifts, the error
+ on rr is still at most ulp(t)=ulp(s) */
+ expr += mpz_normalize(rr, rr, mpz_sizeinbase(t, 2));
+ } while (mpz_cmp_ui(t, 0));
+
+ TMP_FREE(marker);
+ return l;
+}
+
+/* s <- 1 + r/1! + r^2/2! + ... + r^l/l! while MPFR_EXP(r^l/l!)+MPFR_EXPR(r)>-q
+ using Brent/Kung method with O(sqrt(l)) multiplications.
+ Return l.
+ Uses m multiplications of full size and 2l/m of decreasing size,
+ i.e. a total equivalent to about m+l/m full multiplications,
+ i.e. 2*sqrt(l) for m=sqrt(l).
+ Version using mpz. ss must have at least (sizer+1) limbs.
+ The error is bounded by (l^2+4*l) ulps where l is the return value.
+*/
+int
+#if __STDC__
+mpfr_exp2_aux2 (mpz_t s, mpfr_srcptr r, int q, int *exps)
+#else
+mpfr_exp2_aux2 (s, r, q, exps)
+ mpz_t s;
+ mpfr_srcptr r;
+ int q;
+ int *exps;
+#endif
+{
+ int expr, l, m, i, sizer, *expR, expt, ql;
+ unsigned long int c;
+ mpz_t t, *R, rr, tmp;
+ TMP_DECL(marker);
+
+ /* estimate value of l */
+ l = q / (-MPFR_EXP(r));
+ m = (int) _mpfr_isqrt (l);
+ /* we access R[2], thus we need m >= 2 */
+ if (m < 2) m = 2;
+ TMP_MARK(marker);
+ R = (mpz_t*) TMP_ALLOC((m+1)*sizeof(mpz_t)); /* R[i] stands for r^i */
+ expR = (int*) TMP_ALLOC((m+1)*sizeof(int)); /* exponent for R[i] */
+ sizer = 1 + (MPFR_PREC(r)-1)/BITS_PER_MP_LIMB;
+ mpz_init(tmp);
+ MY_INIT_MPZ(rr, sizer+2);
+ MY_INIT_MPZ(t, 2*sizer); /* double size for products */
+ mpz_set_ui(s, 0); *exps = 1-q; /* initialize s to zero, 1 ulp = 2^(1-q) */
+ for (i=0;i<=m;i++) MY_INIT_MPZ(R[i], sizer+2);
+ expR[1] = mpz_set_fr(R[1], r); /* exact operation: no error */
+ expR[1] = mpz_normalize2(R[1], R[1], expR[1], 1-q); /* error <= 1 ulp */
+ mpz_mul(t, R[1], R[1]); /* err(t) <= 2 ulps */
+ mpz_div_2exp(R[2], t, q-1); /* err(R[2]) <= 3 ulps */
+ expR[2] = 1-q;
+ for (i=3;i<=m;i++) {
+ mpz_mul(t, R[i-1], R[1]); /* err(t) <= 2*i-2 */
+ mpz_div_2exp(R[i], t, q-1); /* err(R[i]) <= 2*i-1 ulps */
+ expR[i] = 1-q;
+ }
+ mpz_set_ui(R[0], 1); mpz_mul_2exp(R[0], R[0], q-1); expR[0]=1-q; /* R[0]=1 */
+ mpz_set_ui(rr, 1); expr=0; /* rr contains r^l/l! */
+ /* by induction: err(rr) <= 2*l ulps */
+
+ l = 0;
+ ql = q; /* precision used for current giant step */
+ do {
+ /* all R[i] must have exponent 1-ql */
+ if (l) for (i=0;i<m;i++) {
+ expR[i] = mpz_normalize2(R[i], R[i], expR[i], 1-ql);
+ }
+ /* the absolute error on R[i]*rr is still 2*i-1 ulps */
+ expt = mpz_normalize2(t, R[m-1], expR[m-1], 1-ql);
+ /* err(t) <= 2*m-1 ulps */
+ /* computes t = 1 + r/(l+1) + ... + r^(m-1)*l!/(l+m-1)!
+ using Horner's scheme */
+ for (i=m-2;i>=0;i--) {
+ mpz_div_ui(t, t, l+i+1); /* err(t) += 1 ulp */
+ mpz_add(t, t, R[i]);
+ }
+ /* now err(t) <= (3m-2) ulps */
+
+ /* now multiplies t by r^l/l! and adds to s */
+ mpz_mul(t, t, rr); expt += expr;
+ expt = mpz_normalize2(t, t, expt, *exps);
+ /* err(t) <= (3m-1) + err_rr(l) <= (3m-2) + 2*l */
+#ifdef DEBUG
+ if (expt != *exps) {
+ fprintf(stderr, "Error: expt != exps %d %d\n", expt, *exps); exit(1);
+ }
+#endif
+ mpz_add(s, s, t); /* no error here */
+
+ /* updates rr, the multiplication of the factors l+i could be done
+ using binary splitting too, but it is not sure it would save much */
+ mpz_mul(t, rr, R[m]); /* err(t) <= err(rr) + 2m-1 */
+ expr += expR[m];
+ mpz_set_ui (tmp, 1);
+ for (i=1, c=1; i<=m; i++) {
+ if (l+i > ~((unsigned long int) 0)/c) {
+ mpz_mul_ui(tmp, tmp, c);
+ c = l+i;
+ }
+ else c *= (unsigned long int) l+i;
+ }
+ if (c != 1) mpz_mul_ui (tmp, tmp, c); /* tmp is exact */
+ mpz_fdiv_q(t, t, tmp); /* err(t) <= err(rr) + 2m */
+ expr += mpz_normalize(rr, t, ql); /* err_rr(l+1) <= err_rr(l) + 2m+1 */
+ ql = q - *exps - mpz_sizeinbase(s, 2) + expr + mpz_sizeinbase(rr, 2);
+ l+=m;
+ } while (expr+mpz_sizeinbase(rr, 2) > -q);
+
+ TMP_FREE(marker);
+ mpz_clear(tmp);
+ return l;
+}
diff --git a/mpfr/exp3.c b/mpfr/exp3.c
new file mode 100644
index 000000000..42819d5d8
--- /dev/null
+++ b/mpfr/exp3.c
@@ -0,0 +1,250 @@
+/* mpfr_exp -- exponential of a floating-point number
+
+Copyright (C) 1999 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+/* #define DEBUG */
+
+int mpfr_exp_rational (mpfr_ptr, mpz_srcptr, int, int);
+int mpfr_exp3 (mpfr_ptr, mpfr_srcptr, mp_rnd_t);
+
+int
+#if __STDC__
+mpfr_exp_rational (mpfr_ptr y, mpz_srcptr p, int r, int m)
+#else
+mpfr_exp_rational (y, p, r, m)
+ mpfr_ptr y;
+ mpz_srcptr p;
+ int r;
+ int m;
+#endif
+{
+ int n,i,k,j,l;
+ mpz_t* P,*S;
+ mpz_t* ptoj;
+ int diff,expo;
+ int precy = MPFR_PREC(y);
+ int * mult;
+ int prec_i_have;
+ int *nb_terms;
+ int accu;
+ TMP_DECL (marker);
+
+ TMP_MARK (marker);
+ n = 1 << m;
+ P = (mpz_t*) TMP_ALLOC((m+1) * sizeof(mpz_t));
+ S = (mpz_t*) TMP_ALLOC((m+1) * sizeof(mpz_t));
+ ptoj = (mpz_t*) TMP_ALLOC((m+1) * sizeof(mpz_t)); /* ptoj[i] = mantissa^(2^i) */
+ mult = (int*) TMP_ALLOC((m+1) * sizeof(int));
+ nb_terms = (int*) TMP_ALLOC((m+1) * sizeof(int));
+ mult[0] = 0;
+ for (i=0;i<=m;i++) { mpz_init(P[i]); mpz_init(S[i]); mpz_init(ptoj[i]); }
+ mpz_set(ptoj[0], p);
+ for (i=1;i<m;i++) mpz_mul(ptoj[i], ptoj[i-1], ptoj[i-1]);
+ mpz_set_ui(P[0], 1);
+ mpz_set_ui(S[0], 1);
+ k = 0;
+ nb_terms[0] = 1;
+ prec_i_have = 0;
+ for (i=1;(prec_i_have < precy) && (i < n) ;i++) {
+ k++;
+ nb_terms[k] = 1;
+ mpz_set_ui(P[k], i+1);
+ mpz_set(S[k], P[k]);;
+ j=i+1; l=0; while ((j & 1) == 0) {
+ mpz_mul(S[k], S[k], ptoj[l]);
+ mpz_mul(S[k-1], S[k-1], P[k]);
+ mpz_mul_2exp(S[k-1], S[k-1], r*(1<<l));
+ mpz_add(S[k-1], S[k-1], S[k]);
+ mpz_mul(P[k-1], P[k-1], P[k]);
+ nb_terms[k-1] = nb_terms[k-1]+ nb_terms[k];
+ mult[k] = mult[k-1] + (1 << l)*(r >> 2) + mpz_sizeinbase(P[k],2) - 1;
+ prec_i_have = mult[k];
+ l++; j>>=1; k--;
+ }
+ }
+ l = 0;
+ accu = 0;
+ while (k > 0){
+ mpz_mul(S[k], S[k], ptoj[_mpfr_ceil_log2((double) nb_terms[k])]);
+ mpz_mul(S[k-1], S[k-1], P[k]);
+ accu += nb_terms[k];
+ mpz_mul_2exp(S[k-1], S[k-1], r* accu);
+ mpz_add(S[k-1], S[k-1], S[k]);
+ mpz_mul(P[k-1], P[k-1], P[k]);
+ l++; k--;
+ }
+
+ diff = mpz_sizeinbase(S[0],2) - 2*precy;
+ expo = diff;
+ if (diff >=0)
+ {
+ mpz_div_2exp(S[0],S[0],diff);
+ } else
+ {
+ mpz_mul_2exp(S[0],S[0],-diff);
+ }
+ diff = mpz_sizeinbase(P[0],2) - precy;
+ expo -= diff;
+ if (diff >=0)
+ {
+ mpz_div_2exp(P[0],P[0],diff);
+ } else
+ {
+ mpz_mul_2exp(P[0],P[0],-diff);
+ }
+
+ mpz_tdiv_q(S[0], S[0], P[0]);
+ mpfr_set_z(y,S[0], GMP_RNDD);
+ MPFR_EXP(y) += expo;
+
+ mpfr_div_2exp(y, y, r*(i-1),GMP_RNDN);
+ for (i=0;i<=m;i++) { mpz_clear(P[i]); mpz_clear(S[i]); mpz_clear(ptoj[i]); }
+ TMP_FREE (marker);
+ return 0;
+}
+
+#define shift (BITS_PER_MP_LIMB/2)
+
+int
+#if __STDC__
+mpfr_exp3 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
+#else
+mpfr_exp3 (y, x, rnd_mode)
+ mpfr_ptr y;
+ mpfr_srcptr x;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ mpfr_t t;
+ mpfr_t x_copy;
+ int i,k;
+ mpz_t uk;
+ mpfr_t tmp;
+ int ttt;
+ int twopoweri;
+ int Prec;
+ int loop;
+ int prec_x;
+ int shift_x = 0;
+ int good = 0;
+ int realprec = 0;
+ int iter;
+ int logn;
+
+ /* commencons par 0 */
+ if (MPFR_IS_NAN(x)) { MPFR_SET_NAN(y); return 1; }
+
+ if (MPFR_IS_INF(x))
+ {
+ if (MPFR_SIGN(x) > 0)
+ { MPFR_SET_INF(y); if (MPFR_SIGN(y) == -1) { MPFR_CHANGE_SIGN(y); } }
+ else
+ { MPFR_SET_ZERO(y); if (MPFR_SIGN(y) == -1) { MPFR_CHANGE_SIGN(y); } }
+ /* TODO: conflits entre infinis et zeros ? */
+ }
+
+ if (!MPFR_NOTZERO(x)) {
+ mpfr_set_ui(y, 1, GMP_RNDN);
+ return 0;
+ }
+
+ /* Decomposer x */
+ /* on commence par ecrire x = 1.xxxxxxxxxxxxx
+ ----- k bits -- */
+ prec_x = _mpfr_ceil_log2 ((double) (MPFR_PREC(x)) / BITS_PER_MP_LIMB);
+ if (prec_x < 0) prec_x = 0;
+ logn = _mpfr_ceil_log2 ((double) prec_x + MPFR_PREC(y));
+ if (logn < 2) logn = 2;
+ ttt = MPFR_EXP(x);
+ mpfr_init2(x_copy,MPFR_PREC(x));
+ mpfr_set(x_copy,x,GMP_RNDD);
+ /* on fait le shift pour que le nombre soit inferieur a 1 */
+ if (ttt > 0)
+ {
+ shift_x = ttt;
+ mpfr_mul_2exp(x_copy,x,-ttt, GMP_RNDN);
+ ttt = MPFR_EXP(x_copy);
+ }
+ realprec = MPFR_PREC(y)+logn;
+ mpz_init (uk);
+ while (!good){
+ Prec = realprec+shift+2+shift_x;
+ k = _mpfr_ceil_log2 ((double) Prec / BITS_PER_MP_LIMB);
+
+ /* now we have to extract */
+ mpfr_init2(t, Prec);
+ mpfr_init2(tmp, Prec);
+ mpfr_set_ui(tmp,1,GMP_RNDN);
+ twopoweri = BITS_PER_MP_LIMB;
+ if (k <= prec_x) iter = k; else iter= prec_x;
+ for(i = 0; i <= iter; i++){
+ mpfr_extract (uk, x_copy, i);
+#ifdef DEBUG
+ mpz_out_str(stderr,2, uk);
+ fprintf(stderr, "---\n");
+ fprintf(stderr, "---%d\n", twopoweri - ttt);
+#endif
+ if (i)
+ mpfr_exp_rational (t, uk, twopoweri - ttt, k - i + 1);
+ else
+ {
+ /* cas particulier : on est oblige de faire les calculs avec x/2^.
+ puis elever au carre (plus rapide) */
+ mpfr_exp_rational (t, uk, shift + twopoweri - ttt, k+1);
+ for (loop= 0 ; loop < shift; loop++)
+ mpfr_mul(t,t,t,GMP_RNDD);
+
+ }
+ mpfr_mul(tmp,tmp,t,GMP_RNDD);
+#ifdef DEBUG
+ fprintf(stderr, "fin\n");
+ mpfr_out_str(stderr, 2, MPFR_PREC(y), t, GMP_RNDD);
+ fprintf(stderr, "\n ii --- ii \n");
+#endif
+ twopoweri <<= 1;
+ }
+ for (loop= 0 ; loop < shift_x; loop++)
+ mpfr_mul(tmp,tmp,tmp,GMP_RNDD);
+ mpfr_clear(t);
+ if (mpfr_can_round(tmp, realprec, GMP_RNDD, rnd_mode, MPFR_PREC(y))){
+ mpfr_set(y,tmp,rnd_mode);
+ mpfr_clear(tmp);
+ good = 1;
+ } else {
+ mpfr_clear(tmp);
+ realprec += 3*logn;
+ }
+ }
+ mpz_clear (uk);
+ mpfr_clear(x_copy);
+ return 0;
+}
+
+
+
+
+
+
diff --git a/mpfr/extract.c b/mpfr/extract.c
new file mode 100644
index 000000000..ccfd380b7
--- /dev/null
+++ b/mpfr/extract.c
@@ -0,0 +1,66 @@
+/* mpfr_extract -- bit-extraction function for the binary splitting algorithm
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+#include "gmp-impl.h"
+
+
+/* given 0 <= |p| < 1, this function extracts limbs of p and puts them in y.
+ It is mainly designed for the "binary splitting" algorithm together with
+ generic.c.
+
+ More precisely, if B = 2^BITS_PER_MP_LIMB:
+ - for i=0, y = floor(p * B)
+ - for i>0, y = (p * B^(2^i)) mod B^(2^(i-1))
+ */
+void
+#if __STDC__
+mpfr_extract (mpz_ptr y, mpfr_srcptr p, unsigned int i)
+#else
+mpfr_extract (y, p, i)
+ mpz_ptr y;
+ mpfr_srcptr p;
+ unsigned int i;
+#endif
+{
+ int two_i = 1 << i;
+ int two_i_2 = i ? two_i / 2 : 1;
+ mp_size_t size_p = MPFR_ABSSIZE(p);
+
+ /* as 0 <= |p| < 1, we don't have to care with infinities, NaN, ... */
+
+ _mpz_realloc (y, two_i_2);
+ if (size_p < two_i) {
+ MPN_ZERO (PTR(y), two_i_2);
+ if (size_p >= two_i_2)
+ MPN_COPY (PTR(y) + two_i - size_p, MPFR_MANT(p), size_p - two_i_2);
+ }
+ else
+ MPN_COPY (PTR(y), MPFR_MANT(p) + size_p - two_i, two_i_2);
+
+ MPN_NORMALIZE (PTR(y), two_i_2);
+ SIZ(y) = (MPFR_ISNEG(p)) ? -two_i_2 : two_i_2;
+}
+
+
+
diff --git a/mpfr/generic.c b/mpfr/generic.c
new file mode 100644
index 000000000..f44e5d1c7
--- /dev/null
+++ b/mpfr/generic.c
@@ -0,0 +1,230 @@
+/*
+
+Copyright (C) 1999 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPdFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#ifndef GENERIC
+# error You should specify a name
+#endif
+
+/* TODO: Reflechir a un traitement generique des infinis ? */
+
+#ifdef B
+# ifndef A
+# error B cannot be used without A
+# endif
+#endif
+
+/* Calcule les 2^m premiers termes de la serie hypergeometrique
+ avec x = p / 2^r */
+int
+#if __STDC__
+GENERIC (mpfr_ptr y, mpz_srcptr p, int r, int m)
+#else
+GENERIC (y, p, r, m)
+ mpfr_ptr y;
+ mpz_srcptr p;
+ int r;
+ int m;
+#endif
+{
+ int n,i,k,j,l;
+ int is_p_one = 0;
+ mpz_t* P,*S;
+#ifdef A
+ mpz_t *T;
+#endif
+ mpz_t* ptoj;
+#ifdef R_IS_RATIONAL
+ mpz_t* qtoj;
+ mpfr_t tmp;
+#endif
+ int diff,expo;
+ int precy = MPFR_PREC(y);
+ MPFR_CLEAR_FLAGS(y);
+ n = 1 << m;
+ P = (mpz_t*) (*_mp_allocate_func) ((m+1) * sizeof(mpz_t));
+ S = (mpz_t*) (*_mp_allocate_func) ((m+1) * sizeof(mpz_t));
+ ptoj = (mpz_t*) (*_mp_allocate_func) ((m+1) * sizeof(mpz_t)); /* ptoj[i] = mantissa^(2^i) */
+#ifdef A
+ T = (mpz_t*) (*_mp_allocate_func) ((m+1) * sizeof(mpz_t));
+#endif
+#ifdef R_IS_RATIONAL
+ qtoj = (mpz_t*) (*_mp_allocate_func) ((m+1) * sizeof(mpz_t));
+#endif
+ if ((P == NULL) || (S == NULL) || (ptoj == NULL)
+#ifdef A
+ || (T == NULL)
+#endif
+#ifdef R_IS_RATIONAL
+ || (qtoj == NULL)
+#endif
+ ) {
+ fprintf (stderr, "Error in mpfr_generic: no more memory available\n");
+ exit (1);
+ }
+ for (i=0;i<=m;i++) { mpz_init(P[i]); mpz_init(S[i]); mpz_init(ptoj[i]);
+#ifdef R_IS_RATIONAL
+ mpz_init(qtoj[i]);
+#endif
+#ifdef A
+ mpz_init(T[i]);
+#endif
+ }
+ mpz_set(ptoj[0], p);
+#ifdef C
+# if C2 != 1
+ mpz_mul_ui(ptoj[0], ptoj[0], C2);
+# endif
+#endif
+ is_p_one = !mpz_cmp_si(ptoj[0], 1);
+#ifdef A
+# ifdef B
+ mpz_set_ui(T[0], A1 * B1);
+# else
+ mpz_set_ui(T[0], A1);
+# endif
+#endif
+ if (!is_p_one)
+ for (i=1;i<m;i++) mpz_mul(ptoj[i], ptoj[i-1], ptoj[i-1]);
+#ifdef R_IS_RATIONAL
+ mpz_set_si(qtoj[0], r);
+ for (i=1;i<=m;i++)
+ {
+ mpz_mul(qtoj[i], qtoj[i-1], qtoj[i-1]);
+ }
+#endif
+
+ mpz_set_ui(P[0], 1);
+ mpz_set_ui(S[0], 1);
+ k = 0;
+ for (i=1;(i < n) ;i++) {
+ k++;
+
+#ifdef A
+# ifdef B
+ mpz_set_ui(T[k], (A1 + A2*i)*(B1+B2*i));
+# else
+ mpz_set_ui(T[k], A1 + A2*i);
+# endif
+#endif
+
+#ifdef C
+# ifdef NO_FACTORIAL
+ mpz_set_ui(P[k], (C1 + C2 * (i-1)));
+ mpz_set_ui(S[k], 1);
+# else
+ mpz_set_ui(P[k], (i+1) * (C1 + C2 * (i-1)));
+ mpz_set_ui(S[k], i+1);
+# endif
+#else
+# ifdef NO_FACTORIAL
+ mpz_set_ui(P[k], 1);
+# else
+ mpz_set_ui(P[k], i+1);
+# endif
+ mpz_set(S[k], P[k]);
+#endif
+ j=i+1; l=0; while ((j & 1) == 0) {
+ if (!is_p_one)
+ mpz_mul(S[k], S[k], ptoj[l]);
+#ifdef A
+# ifdef B
+# if (A2*B2) != 1
+ mpz_mul_ui(P[k], P[k], A2*B2);
+# endif
+# else
+# if A2 != 1
+ mpz_mul_ui(P[k], P[k], A2);
+# endif
+#endif
+ mpz_mul(S[k], S[k], T[k-1]);
+#endif
+ mpz_mul(S[k-1], S[k-1], P[k]);
+#ifdef R_IS_RATIONAL
+ mpz_mul(S[k-1], S[k-1], qtoj[l]);
+#else
+ mpz_mul_2exp(S[k-1], S[k-1], r*(1<<l));
+#endif
+ mpz_add(S[k-1], S[k-1], S[k]);
+ mpz_mul(P[k-1], P[k-1], P[k]);
+#ifdef A
+ mpz_mul(T[k-1], T[k-1], T[k]);
+#endif
+ l++; j>>=1; k--;
+ }
+ }
+
+ diff = mpz_sizeinbase(S[0],2) - 2*precy;
+ expo = diff;
+ if (diff >=0)
+ {
+ mpz_div_2exp(S[0],S[0],diff);
+ } else
+ {
+ mpz_mul_2exp(S[0],S[0],-diff);
+ }
+ diff = mpz_sizeinbase(P[0],2) - precy;
+ expo -= diff;
+ if (diff >=0)
+ {
+ mpz_div_2exp(P[0],P[0],diff);
+ } else
+ {
+ mpz_mul_2exp(P[0],P[0],-diff);
+ }
+
+ mpz_tdiv_q(S[0], S[0], P[0]);
+ mpfr_set_z(y,S[0], GMP_RNDD);
+ MPFR_EXP(y) += expo;
+
+#ifdef R_IS_RATIONAL
+ /* division exacte */
+ mpz_div_ui(qtoj[m], qtoj[m], r);
+ i = (MPFR_PREC(y));
+ mpfr_init2(tmp,i);
+ mpfr_set_z(tmp, qtoj[m] , GMP_RNDD);
+ mpfr_div(y, y, tmp,GMP_RNDD);
+ mpfr_clear(tmp);
+#else
+ mpfr_div_2exp(y, y, r*(i-1),GMP_RNDN);
+#endif
+ for (i=0;i<=m;i++) { mpz_clear(P[i]); mpz_clear(S[i]); mpz_clear(ptoj[i]);
+#ifdef R_IS_RATIONAL
+ mpz_clear(qtoj[i]);
+#endif
+#ifdef A
+ mpz_clear(T[i]);
+#endif
+ }
+ (*_mp_free_func) (P, (m+1) * sizeof(mpz_t));
+ (*_mp_free_func) (S, (m+1) * sizeof(mpz_t));
+ (*_mp_free_func) (ptoj, (m+1) * sizeof(mpz_t));
+#ifdef R_IS_RATIONAL
+ (*_mp_free_func) (qtoj, (m+1) * sizeof(mpz_t));
+#endif
+#ifdef A
+ (*_mp_free_func) (T, (m+1) * sizeof(mpz_t));
+#endif
+ return 0;
+}
+
+
+
+
diff --git a/mpfr/get_str.c b/mpfr/get_str.c
index 7cd7d5d00..9c1391c19 100644
--- a/mpfr/get_str.c
+++ b/mpfr/get_str.c
@@ -1,6 +1,6 @@
/* mpfr_get_str -- output a floating-point number to a string
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -19,7 +19,8 @@ along with the MPFR Library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
-#include <math.h>
+/* #define DEBUG */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -27,6 +28,7 @@ MA 02111-1307, USA. */
#include "gmp-impl.h"
#include "longlong.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
/*
Convert op to a string in base 'base' with 'n' digits and writes the
@@ -37,32 +39,54 @@ 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=NULL; mp_rnd_t rnd1; int f, pow2, ok=0, neg;
if (base<2 || 36<base) {
fprintf(stderr, "Error: too small or too large base in mpfr_get_str: %d\n",
base);
exit(1);
}
+
+ neg = (MPFR_SIGN(op)<0) ? 1 : 0;
+
+ if (MPFR_IS_INF(op)) {
+ if (str == NULL) {
+ str = (*_mp_allocate_func)(neg + 4);
+ if (str == NULL) {
+ fprintf (stderr, "Error in mpfr_get_str: no more memory available\n");
+ exit (1);
+ }
+ }
+ str0 = str;
+ if (neg) { *str++ = '-'; }
+ *str++ = 'I'; *str++ = 'n'; *str++ = 'f'; *str='\0';
+ return str0;
+ }
- neg = (SIGN(op)<0) ? 1 : 0;
-
- if (!NOTZERO(op)) {
- if (str==NULL) str0=str=(*__gmp_allocate_func)(neg + n + 2);
- if (SIGN(op)<0) *str++ = '-';
+ if (!MPFR_NOTZERO(op)) {
+ if (str == NULL) {
+ str = (*_mp_allocate_func)(neg + n + 1);
+ if (str == NULL) {
+ fprintf (stderr, "Error in mpfr_get_str: no more memory available\n");
+ exit (1);
+ }
+ }
+ str0 = str;
+ if (MPFR_SIGN(op)<0) *str++ = '-';
for (f=0;f<n;f++) *str++ = '0';
+ *str++ = '\0';
*expptr = 1;
return str0;
}
@@ -73,29 +97,41 @@ char *mpfr_get_str(str, expptr, base, n, op, rnd_mode)
/* if pow2 <> 0, then base = 2^pow2 */
/* first determines the exponent */
- e = EXP(op);
- d = fabs(mpfr_get_d2(op, 0));
+ e = MPFR_EXP(op);
+ d = ABS(mpfr_get_d2(op, 0));
/* the absolute value of op is between 1/2*2^e and 2^e */
/* the output exponent f is such that base^(f-1) <= |op| < base^f
i.e. f = 1 + floor(log(|op|)/log(base))
= 1 + floor((log(|m|)+e*log(2))/log(base)) */
- f = 1 + (int) floor((log(d)+(double)e*log(2.0))/log((double)base));
+ /* f = 1 + (int) floor((log(d)/LOG2+(double)e)*LOG2/log((double)base)); */
+ d = ((double) e + (double) _mpfr_floor_log2(d))
+ * __mp_bases[base].chars_per_bit_exactly;
+ /* warning: (int) d rounds towards 0 */
+ f = (int) d; /* f equals floor(d) if d >= 0 and ceil(d) if d < 0 */
+ if (f <= d) f++;
if (n==0) {
- /* performs exact rounding, i.e. returns y such that for rnd_mode=RNDN
- for example, we have:
- 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)
+ /* performs exact rounding, i.e. returns y such that for GMP_RNDU
+ for example, we have: x*2^(e-p) <= y*base^(f-n)
*/
- n = f + (int) ceil(((double)PREC(op)-e)*log(2.0)/log((double)base));
+ n = (int) (__mp_bases[base].chars_per_bit_exactly * MPFR_PREC(op));
+ if (n==0) n=1;
}
+#ifdef DEBUG
+ printf("f=%d n=%d MPFR_EXP(op)=%d MPFR_PREC(op)=%d\n", f, n, e, MPFR_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));
+ if (pow2) prec = n*pow2;
+ else
+ prec = 1 + (long) ((double) n / __mp_bases[base].chars_per_bit_exactly);
+#ifdef DEBUG
+ printf("prec=%d\n", prec);
+#endif
err = 5;
q = prec+err;
/* one has to use at least q bits */
q = (((q-1)/BITS_PER_MP_LIMB)+1)*BITS_PER_MP_LIMB;
- mpfr_init2(a,q); mpfr_init2(b,q);
+ mpfr_init2(a, q); mpfr_init2(b, q);
do {
p = n-f; if ((div=(p<0))) p=-p;
@@ -126,80 +162,66 @@ 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("base^(n-f)=%1.20e\n", mpfr_get_d(a));
+#endif
mpfr_mul(b, op, a, rnd_mode);
}
}
- if (neg) CHANGE_SIGN(b); /* put b positive */
-
+ if (neg) MPFR_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);
- }
+ /* if the intermediate precision exceeds twice that of the input,
+ a worst-case for the division cannot occur */
+ ok=1;
+ rnd_mode=GMP_RNDN;
}
- ok = pow2 || mpfr_can_round(b, q-err, rnd_mode, rnd_mode, prec);
+ else ok = pow2 || mpfr_can_round(b, q-err, rnd_mode, rnd_mode, prec);
- if (ok) {
- if (pow2) {
- sh = e-PREC(op) + pow2*(n-f); /* error at most 2^e */
- ok = mpfr_can_round(b, EXP(b)-sh-1, rnd_mode, rnd_mode, n*pow2);
- }
- else {
- /* check that value is the same at distance 2^(e-PREC(op))/base^(f-n)
- in opposite from rounding direction */
- if (e>=PREC(op)) mpfr_mul_2exp(a, a, e-PREC(op), rnd_mode);
- else mpfr_div_2exp(a, a, PREC(op)-e, rnd_mode);
- if (rnd_mode==GMP_RNDN) {
- mpfr_div_2exp(a, a, 2, rnd_mode);
- mpfr_sub(b, b, a, rnd_mode); /* b - a/2 */
- mpfr_mul_2exp(a, a, 2, rnd_mode);
- mpfr_add(a, b, a, rnd_mode); /* b + a/2 */
- }
- 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);
- /* check that a and b are rounded similarly */
- prec=EXP(b);
- if (EXP(a) != prec) ok=0;
- else {
- mpfr_round(b, rnd_mode, prec);
- mpfr_round(a, rnd_mode, prec);
- 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);
- }
- q -= BITS_PER_MP_LIMB;
- }
- }
} while (ok==0 && (q+=BITS_PER_MP_LIMB) );
+
if (neg)
switch (rnd_mode) {
case GMP_RNDU: rnd_mode=GMP_RNDZ; break;
case GMP_RNDD: rnd_mode=GMP_RNDU; break;
}
- prec=EXP(b); /* may have changed due to rounding */
+ if (ok) mpfr_round(b, rnd_mode, MPFR_EXP(b));
+
+ prec=MPFR_EXP(b); /* may have changed due to rounding */
/* now the mantissa is the integer part of b */
mpz_init(bz); q=1+(prec-1)/BITS_PER_MP_LIMB;
_mpz_realloc(bz, q);
sh = prec%BITS_PER_MP_LIMB;
- e = 1 + (PREC(b)-1)/BITS_PER_MP_LIMB-q;
- if (sh) mpn_rshift(PTR(bz), MANT(b)+e, q, BITS_PER_MP_LIMB-sh);
- else MPN_COPY(PTR(bz), MANT(b)+e, q);
+ e = 1 + (MPFR_PREC(b)-1)/BITS_PER_MP_LIMB-q;
+ if (sh) mpn_rshift(PTR(bz), MPFR_MANT(b)+e, q, BITS_PER_MP_LIMB-sh);
+ else MPN_COPY(PTR(bz), MPFR_MANT(b)+e, q);
bz->_mp_size=q;
/* computes the number of characters needed */
q = neg + n + 2; /* n+1 may not be enough for 100000... */
- if (str==NULL) str0=str=(*__gmp_allocate_func)(q);
+ if (str == NULL) {
+ str0 = str = (*_mp_allocate_func)(q);
+ if (str == NULL) {
+ fprintf (stderr, "Error in mpfr_get_str: no more memory available\n");
+ exit (1);
+ }
+ }
if (neg) *str++='-';
mpz_get_str(str, base, bz); /* n digits of mantissa */
- if (strlen(str)==n+1) f++; /* possible due to rounding */
+ if (strlen(str)==n+1) {
+ f++; /* possible due to rounding */
+ str[n]='\0'; /* ensures we get only n digits of output */
+ }
+ else if (strlen(str)==n-1) {
+ f--;
+ str[n-1]='0';
+ str[n]='\0';
+ }
*expptr = f;
mpfr_clear(a); mpfr_clear(b); mpz_clear(bz);
return str0;
diff --git a/mpfr/init.c b/mpfr/init.c
index 37f03536c..7f95c4159 100644
--- a/mpfr/init.c
+++ b/mpfr/init.c
@@ -1,6 +1,6 @@
/* mpfr_init -- initialize a floating-point number
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -23,27 +23,44 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
void
#if __STDC__
-mpfr_init2 (mpfr_t x, unsigned long int p)
+mpfr_init2 (mpfr_ptr x, mp_prec_t p)
#else
mpfr_init2 (x, p)
- mpfr_t x;
- unsigned long int p;
+ mpfr_ptr x;
+ mp_prec_t p;
#endif
{
- unsigned long xsize;
+ mp_prec_t xsize;
if (p==0) {
- printf("*** cannot initialize mpfr with precision 0\n"); exit(1);
+ fprintf(stderr, "*** cannot initialize mpfr with precision 0\n"); exit(1);
}
xsize = (p - 1)/BITS_PER_MP_LIMB + 1;
- x -> _mp_prec = p;
- x -> _mp_d = (mp_ptr) (*__gmp_allocate_func)
- (xsize * BYTES_PER_MP_LIMB);
- x -> _mp_size = xsize;
- x -> _mp_exp = 0; /* avoids uninitialized memory reads for zero */
+ MPFR_PREC(x) = p;
+ MPFR_MANT(x) = (mp_ptr) (*_mp_allocate_func) (xsize * BYTES_PER_MP_LIMB);
+ if (MPFR_MANT(x) == NULL) {
+ fprintf (stderr, "Error in mpfr_init2: no more memory available\n");
+ exit (1);
+ }
+ MPFR_SIZE(x) = xsize;
+ MPFR_CLEAR_FLAGS(x);
+ MPFR_SET_ZERO(x); /* initializes to zero */
+ MPFR_EXP(x) = 0; /* avoids uninitialized memory reads for zero */
+}
+
+void
+#if __STDC__
+mpfr_init (mpfr_ptr x)
+#else
+mpfr_init (x)
+ mpfr_ptr x;
+#endif
+{
+ mpfr_init2(x, __gmp_default_fp_bit_precision);
}
diff --git a/mpfr/inp_str.c b/mpfr/inp_str.c
new file mode 100644
index 000000000..3a6d847f9
--- /dev/null
+++ b/mpfr/inp_str.c
@@ -0,0 +1,105 @@
+/* mpf_inp_str(dest_float, stream, base) -- Input a number in base
+ BASE from stdio stream STREAM and store the result in DEST_FLOAT.
+
+Copied from GMP, file mpf/inp_str.c.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+size_t
+#if __STDC__
+mpfr_inp_str (mpfr_ptr rop, FILE *stream, int base, mp_rnd_t rnd_mode)
+#else
+mpfr_inp_str (rop, stream, base, rnd_mode)
+ mpfr_ptr rop;
+ FILE *stream;
+ int base;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ char *str;
+ size_t alloc_size, str_size;
+ int c;
+ size_t retval;
+ size_t nread;
+
+ MPFR_CLEAR_FLAGS(rop);
+ if (stream == 0)
+ stream = stdin;
+
+ alloc_size = 100;
+ str = (char *) (*_mp_allocate_func) (alloc_size);
+ if (str == NULL) {
+ fprintf (stderr, "Error in mpfr_inp_str: no more memory available\n");
+ exit (1);
+ }
+ str_size = 0;
+ nread = 0;
+
+ /* Skip whitespace. */
+ do
+ {
+ c = getc (stream);
+ nread++;
+ }
+ while (isspace (c));
+
+ for (;;)
+ {
+ if (str_size >= alloc_size)
+ {
+ size_t old_alloc_size = alloc_size;
+ alloc_size = alloc_size * 3 / 2;
+ str = (char *) (*_mp_reallocate_func) (str, old_alloc_size, alloc_size);
+ if (str == NULL) {
+ fprintf (stderr, "Error in mpfr_inp_str: no more memory available\n");
+ exit (1);
+ }
+ }
+ if (c == EOF || isspace (c))
+ break;
+ str[str_size++] = c;
+ c = getc (stream);
+ }
+ ungetc (c, stream);
+
+ if (str_size >= alloc_size)
+ {
+ size_t old_alloc_size = alloc_size;
+ alloc_size = alloc_size * 3 / 2;
+ str = (char *) (*_mp_reallocate_func) (str, old_alloc_size, alloc_size);
+ if (str == NULL) {
+ fprintf (stderr, "Error in mpfr_inp_str: no more memory available\n");
+ exit (1);
+ }
+ }
+ str[str_size] = 0;
+
+ retval = mpfr_set_str (rop, str, base, rnd_mode);
+ if (retval == -1)
+ return 0; /* error */
+
+ (*_mp_free_func) (str, alloc_size);
+ return str_size + nread;
+}
diff --git a/mpfr/log.c b/mpfr/log.c
index 06f5dad03..523d19870 100644
--- a/mpfr/log.c
+++ b/mpfr/log.c
@@ -1,6 +1,6 @@
/* mpfr_log -- natural logarithm of a floating-point number
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -20,11 +20,10 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include <stdio.h>
-#include <math.h>
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
-
+#include "mpfr-impl.h"
/* The computation of log(a) is done using the formula :
if we want p bits of the result,
@@ -40,44 +39,66 @@ MA 02111-1307, USA. */
so the relative error 4/s^2 is < 4/2^p i.e. 4 ulps.
*/
-
-#define MON_INIT(xp, x, p, s) xp = (mp_ptr) TMP_ALLOC(s*BYTES_PER_MP_LIMB); x -> _mp_prec = p; x -> _mp_d = xp; x -> _mp_size = s; x -> _mp_exp = 0;
-
/* #define DEBUG */
int
#if __STDC__
-mpfr_log(mpfr_ptr r, mpfr_srcptr a, unsigned char rnd_mode)
+mpfr_log (mpfr_ptr r, mpfr_srcptr a, mp_rnd_t rnd_mode)
#else
-mpfr_log(r, a, rnd_mode)
+mpfr_log (r, a, rnd_mode)
mpfr_ptr r;
mpfr_srcptr a;
- unsigned char rnd_mode;
+ mp_rnd_t rnd_mode;
#endif
{
- int p, m, q, bool, size, cancel;
+ int m, bool, size, cancel;
+ mp_prec_t p, q;
mpfr_t cst, rapport, agm, tmp1, tmp2, s, mm;
mp_limb_t *cstp, *rapportp, *agmp, *tmp1p, *tmp2p, *sp, *mmp;
double ref;
TMP_DECL(marker);
- /* If a is NaN or a is negative or null, the result is NaN */
- if (FLAG_NAN(a) || (SIGN(a)<=0))
- { SET_NAN(r); return 1; }
+ /* If a is NaN, the result is NaN */
+ if (MPFR_IS_NAN(a)) {
+ MPFR_SET_NAN(r);
+ return 1;
+ }
+
+ MPFR_CLEAR_NAN(r);
+
+ /* check for infinity before zero */
+ if (MPFR_IS_INF(a))
+ {
+ MPFR_SET_INF(r);
+ if (MPFR_SIGN(r) > 0) MPFR_CHANGE_SIGN(r);
+ return 1;
+ }
+
+ if (MPFR_IS_ZERO(a))
+ {
+ MPFR_SET_INF(r);
+ if (MPFR_SIGN(r) < 0) MPFR_CHANGE_SIGN(r);
+ return 1;
+ }
+
+ /* Now we can clear the flags without damage even if r == a */
+ MPFR_CLEAR_INF(r);
/* If a is 1, the result is 0 */
if (mpfr_cmp_ui_2exp(a,1,0)==0){
- SET_ZERO(r);
+ MPFR_SET_ZERO(r);
return 0; /* only case where the result is exact */
}
- q=PREC(r);
+ q=MPFR_PREC(r);
ref=mpfr_get_d(a)-1.0;
if (ref<0)
ref=-ref;
- p=q+4;
+ /* use initial precision about q+lg(q)+5 */
+ p=q+5; m=q; while (m) { p++; m >>= 1; }
+
/* adjust to entire limb */
if (p%BITS_PER_MP_LIMB) p += BITS_PER_MP_LIMB - (p%BITS_PER_MP_LIMB);
@@ -89,33 +110,33 @@ mpfr_log(r, a, rnd_mode)
printf("p=%d\n", p);
#endif
/* Calculus of m (depends on p) */
- m=(int) ceil(((double) p)/2.0) -EXP(a)+1;
+ m = (p + 1) / 2 - MPFR_EXP(a) + 1;
/* All the mpfr_t needed have a precision of p */
TMP_MARK(marker);
size=(p-1)/BITS_PER_MP_LIMB+1;
- MON_INIT(cstp, cst, p, size);
- MON_INIT(rapportp, rapport, p, size);
- MON_INIT(agmp, agm, p, size);
- MON_INIT(tmp1p, tmp1, p, size);
- MON_INIT(tmp2p, tmp2, p, size);
- MON_INIT(sp, s, p, size);
- MON_INIT(mmp, mm, p, size);
-
- mpfr_set_si(mm,m,GMP_RNDN); /* I have m, supposed exact */
- mpfr_set_si(tmp1,1,GMP_RNDN); /* I have 1, exact */
- mpfr_set_si(tmp2,4,GMP_RNDN); /* I have 4, exact */
- mpfr_mul_2exp(s,a,m,GMP_RNDN); /* I compute s=a*2^m, err <= 1 ulp */
- mpfr_div(rapport,tmp2,s,GMP_RNDN); /* I compute 4/s, err <= 2 ulps */
- mpfr_agm(agm,tmp1,rapport,GMP_RNDN); /* AG(1,4/s), err<=3 ulps */
- mpfr_mul_2exp(tmp1,agm,1,GMP_RNDN); /* 2*AG(1,4/s), still err<=3 ulps */
- mpfr_pi(cst, GMP_RNDN); /* I compute pi, err<=1ulp */
- mpfr_div(tmp2,cst,tmp1,GMP_RNDN); /* pi/2*AG(1,4/s), err<=5ulps */
- mpfr_log2(cst,GMP_RNDN); /* I compute log(2), err<=1ulp */
+ MPFR_INIT(cstp, cst, p, size);
+ MPFR_INIT(rapportp, rapport, p, size);
+ MPFR_INIT(agmp, agm, p, size);
+ MPFR_INIT(tmp1p, tmp1, p, size);
+ MPFR_INIT(tmp2p, tmp2, p, size);
+ MPFR_INIT(sp, s, p, size);
+ MPFR_INIT(mmp, mm, p, size);
+
+ mpfr_set_si (mm, m, GMP_RNDN); /* I have m, supposed exact */
+ mpfr_set_si (tmp1, 1, GMP_RNDN); /* I have 1, exact */
+ mpfr_set_si (tmp2, 4, GMP_RNDN); /* I have 4, exact */
+ mpfr_mul_2exp (s, a, m, GMP_RNDN); /* I compute s=a*2^m, err <= 1 ulp */
+ mpfr_div (rapport, tmp2, s, GMP_RNDN);/* I compute 4/s, err <= 2 ulps */
+ mpfr_agm (agm, tmp1, rapport, GMP_RNDN); /* AG(1,4/s), err<=3 ulps */
+ mpfr_mul_2exp (tmp1, agm, 1, GMP_RNDN); /* 2*AG(1,4/s), still err<=3 ulps */
+ mpfr_const_pi (cst, GMP_RNDN); /* compute pi, err<=1ulp */
+ mpfr_div (tmp2, cst, tmp1, GMP_RNDN); /* pi/2*AG(1,4/s), err<=5ulps */
+ mpfr_const_log2 (cst, GMP_RNDN); /* compute log(2), err<=1ulp */
mpfr_mul(tmp1,cst,mm,GMP_RNDN); /* I compute m*log(2), err<=2ulps */
- cancel = EXP(tmp2);
+ cancel = MPFR_EXP(tmp2);
mpfr_sub(cst,tmp2,tmp1,GMP_RNDN); /* log(a), err<=7ulps+cancel */
- cancel -= EXP(cst);
+ cancel -= MPFR_EXP(cst);
#ifdef DEBUG
printf("cancelled bits=%d\n", cancel);
printf("approx="); mpfr_print_raw(cst); putchar('\n');
diff --git a/mpfr/log2.c b/mpfr/log2.c
index 151e0e8cb..0c8688eac 100644
--- a/mpfr/log2.c
+++ b/mpfr/log2.c
@@ -1,6 +1,6 @@
-/* mpfr_log2 -- compute natural logarithm of 2
+/* mpfr_const_log2 -- compute natural logarithm of 2
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -20,16 +20,99 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include <stdio.h>
-#include <math.h>
#include "gmp.h"
-#include "gmp-impl.h"
#include "longlong.h"
#include "mpfr.h"
+#include "gmp-impl.h"
+#include "mpfr-impl.h"
+
+mpfr_t __mpfr_const_log2; /* stored value of log(2) */
+int __mpfr_const_log2_prec=0; /* precision of stored value */
+mp_rnd_t __mpfr_const_log2_rnd; /* rounding mode of stored value */
+
+int mpfr_aux_log2 (mpfr_ptr, mpz_srcptr, int, int);
+int mpfr_const_aux_log2 (mpfr_ptr, mp_rnd_t);
+
+#define A
+#define A1 1
+#define A2 1
+#undef B
+#define C
+#define C1 2
+#define C2 1
+#define NO_FACTORIAL
+#undef R_IS_RATIONAL
+#define GENERIC mpfr_aux_log2
+#include "generic.c"
+#undef A
+#undef A1
+#undef A2
+#undef NO_FACTORIAL
+#undef GENERIC
+#undef C
+#undef C1
+#undef C2
+
+int
+#if __STDC__
+mpfr_const_aux_log2 (mpfr_ptr mylog, mp_rnd_t rnd_mode)
+#else
+mpfr_const_aux_log2 (mylog, rnd_mode)
+ mpfr_ptr mylog;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ int prec;
+ mpfr_t tmp1, tmp2, result,tmp3;
+ mpz_t cst;
+ int good = 0;
+ int logn;
+ int prec_i_want = MPFR_PREC(mylog);
+ int prec_x;
+
+ mpz_init(cst);
+ logn = _mpfr_ceil_log2 ((double) MPFR_PREC(mylog));
+ prec_x = prec_i_want + logn;
+ while (!good){
+ prec = _mpfr_ceil_log2 ((double) prec_x);
+ mpfr_init2(tmp1, prec_x);
+ mpfr_init2(result, prec_x);
+ mpfr_init2(tmp2, prec_x);
+ mpfr_init2(tmp3, prec_x);
+ mpz_set_ui(cst, 1);
+ mpfr_aux_log2(tmp1, cst, 4, prec-2);
+ mpfr_div_2exp(tmp1, tmp1, 4,GMP_RNDD);
+ mpfr_mul_ui(tmp1, tmp1, 15,GMP_RNDD);
+
+ mpz_set_ui(cst, 3);
+ mpfr_aux_log2(tmp2, cst, 7, prec-2);
+ mpfr_div_2exp(tmp2, tmp2, 7,GMP_RNDD);
+ mpfr_mul_ui(tmp2, tmp2, 5*3,GMP_RNDD);
+ mpfr_sub(result, tmp1, tmp2, GMP_RNDD);
+
+ mpz_set_ui(cst, 13);
+ mpfr_aux_log2(tmp3, cst, 8, prec-2);
+ mpfr_div_2exp(tmp3, tmp3, 8,GMP_RNDD);
+ mpfr_mul_ui(tmp3, tmp3, 3*13,GMP_RNDD);
+ mpfr_sub(result, result, tmp3, GMP_RNDD);
+
+ mpfr_clear(tmp1);
+ mpfr_clear(tmp2);
+ mpfr_clear(tmp3);
+ if (mpfr_can_round(result, prec_x, GMP_RNDD, rnd_mode, prec_i_want)){
+ mpfr_set(mylog, result, rnd_mode);
+ good = 1;
+ } else
+ {
+ prec_x += logn;
+ }
+ mpfr_clear(result);
+ }
+ mpz_clear(cst);
+ return 0;
+}
-mpfr_t __mpfr_log2; /* stored value of log(2) with rnd_mode=GMP_RNDZ */
-int __mpfr_log2_prec=0; /* precision of stored value */
-
-/* set x to log(2) rounded to precision PREC(x) with direction rnd_mode
+/* set x to log(2) rounded to precision MPFR_PREC(x) with direction rnd_mode
use formula log(2) = sum(1/k/2^k, k=1..infinity)
@@ -44,59 +127,58 @@ int __mpfr_log2_prec=0; /* precision of stored value */
*/
void
#if __STDC__
-mpfr_log2(mpfr_ptr x, unsigned char rnd_mode)
+mpfr_const_log2 (mpfr_ptr x, mp_rnd_t rnd_mode)
#else
-mpfr_log2(x, rnd_mode) mpfr_ptr x; unsigned char rnd_mode;
+mpfr_const_log2 (x, rnd_mode) mpfr_ptr x; mp_rnd_t rnd_mode;
#endif
{
int N, oldN, k, precx; mpz_t s, t, u;
- precx = PREC(x);
+ precx = MPFR_PREC(x);
+ MPFR_CLEAR_FLAGS(x);
/* has stored value enough precision ? */
- if (precx <= __mpfr_log2_prec) {
- if (rnd_mode==GMP_RNDZ || rnd_mode==GMP_RNDD ||
- mpfr_can_round(__mpfr_log2, __mpfr_log2_prec, GMP_RNDZ, rnd_mode, precx))
+ if (precx <= __mpfr_const_log2_prec) {
+ if (rnd_mode==__mpfr_const_log2_rnd || mpfr_can_round(__mpfr_const_log2,
+ __mpfr_const_log2_prec, __mpfr_const_log2_rnd, rnd_mode, precx))
{
- mpfr_set(x, __mpfr_log2, rnd_mode); return;
+ mpfr_set(x, __mpfr_const_log2, rnd_mode); return;
}
}
/* need to recompute */
- N=2;
- do {
- oldN = N;
- N = precx + (int)ceil(log((double)N)/log(2.0));
- } while (N != oldN);
- mpz_init_set_ui(s,0);
- mpz_init(u);
- mpz_init_set_ui(t,1);
-#if 0
- /* use log(2) = sum(1/k/2^k, k=1..infinity) */
- mpz_mul_2exp(t, t, N);
- for (k=1;k<N;k++) {
- mpz_div_2exp(t, t, 1);
- mpz_fdiv_q_ui(u, t, k);
- mpz_add(s, s, u);
- }
-#else
- /* use log(2) = sum((6*k-1)/(2*k^2-k)/2^(2*k+1), k=1..infinity) */
- mpz_mul_2exp(t, t, N-1);
- for (k=1;k<N/2;k++) {
- mpz_div_2exp(t, t, 2);
- mpz_mul_ui(u, t, 6*k-1);
- mpz_fdiv_q_ui(u, u, k*(2*k-1));
- mpz_add(s, s, u);
- }
-#endif
- mpfr_set_z(x, s, rnd_mode);
- EXP(x) -= N;
-
- /* stored computed value */
- if (__mpfr_log2_prec==0) mpfr_init2(__mpfr_log2, precx);
- else mpfr_set_prec(__mpfr_log2, precx);
- mpfr_set(__mpfr_log2, x, GMP_RNDZ);
- __mpfr_log2_prec=precx;
-
- mpz_clear(s); mpz_clear(t); mpz_clear(u);
+ if (precx < 30000){ /* use nai"ve Taylor series evaluation */
+ N=2;
+ do {
+ oldN = N;
+ N = precx + _mpfr_ceil_log2 ((double) N);
+ } while (N != oldN);
+ mpz_init (s); /* set to zero */
+ mpz_init (u);
+ mpz_init_set_ui (t, 1);
+
+ /* use log(2) = sum((6*k-1)/(2*k^2-k)/2^(2*k+1), k=1..infinity) */
+ mpz_mul_2exp (t, t, N-1);
+ for (k=1; k<N/2; k++) {
+ mpz_div_2exp (t, t, 2);
+ mpz_mul_ui (u, t, 6*k-1);
+ mpz_fdiv_q_ui (u, u, k*(2*k-1));
+ mpz_add (s, s, u);
+ }
+
+ mpfr_set_z(x, s, rnd_mode);
+ MPFR_EXP(x) -= N;
+ mpz_clear(s); mpz_clear(t); mpz_clear(u);
+ } else
+ {
+ /* use binary splitting method */
+ mpfr_const_aux_log2(x, rnd_mode);
+ }
+
+ /* store computed value */
+ if (__mpfr_const_log2_prec==0) mpfr_init2(__mpfr_const_log2, precx);
+ else mpfr_set_prec(__mpfr_const_log2, precx);
+ mpfr_set(__mpfr_const_log2, x, rnd_mode);
+ __mpfr_const_log2_prec=precx;
+ __mpfr_const_log2_rnd=rnd_mode;
}
diff --git a/mpfr/mpf2mpfr.h b/mpfr/mpf2mpfr.h
new file mode 100644
index 000000000..0e4704b8c
--- /dev/null
+++ b/mpfr/mpf2mpfr.h
@@ -0,0 +1,144 @@
+/* types */
+#define mpf_t mpfr_t
+
+
+#undef mpf_ceil
+#undef mpf_clear
+#undef mpf_cmp
+#undef mpf_cmp_si
+#undef mpf_cmp_ui
+#undef mpf_eq
+#undef mpf_floor
+#undef mpf_get_d
+#undef mpf_get_prec
+#undef mpf_init
+#undef mpf_init2
+#undef mpf_random2
+#undef mpf_set_default_prec
+#undef mpf_set_prec
+#undef mpf_set_prec_raw
+#undef mpf_trunc
+#undef mpf_sgn
+#undef mpf_swap
+
+/* functions which take as argument the rounding mode */
+#undef mpf_abs
+#undef mpf_add
+#undef mpf_add_ui
+#undef mpf_div
+#undef mpf_div_ui
+#undef mpf_div_2exp
+#undef mpf_dump
+#undef mpf_get_str
+#undef mpf_inp_str
+#undef mpf_set_str
+#undef mpf_init_set
+#undef mpf_init_set_d
+#undef mpf_init_set_si
+#undef mpf_init_set_str
+#undef mpf_init_set_ui
+#undef mpf_mul
+#undef mpf_mul_2exp
+#undef mpf_mul_ui
+#undef mpf_neg
+#undef mpf_out_str
+#undef mpf_pow_ui
+#undef mpf_reldiff
+#undef mpf_set
+#undef mpf_set_d
+#undef mpf_set_q
+#undef mpf_set_si
+#undef mpf_set_ui
+#undef mpf_set_z
+#undef mpf_sqrt
+#undef mpf_sqrt_ui
+#undef mpf_sub
+#undef mpf_sub_ui
+#undef mpf_ui_div
+#undef mpf_ui_sub
+#undef mpf_urandomb
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* functions which don't take as argument the rounding mode */
+#define mpf_ceil mpfr_ceil
+#define mpf_clear mpfr_clear
+#define mpf_cmp mpfr_cmp
+#define mpf_cmp_si mpfr_cmp_si
+#define mpf_cmp_ui mpfr_cmp_ui
+#define mpf_eq mpfr_eq
+#define mpf_floor mpfr_floor
+#define mpf_get_d mpfr_get_d
+#define mpf_get_prec mpfr_get_prec
+#define mpf_init mpfr_init
+#define mpf_init2 mpfr_init2
+#define mpf_random2 mpfr_random2
+#define mpf_set_default_prec mpfr_set_default_prec
+#define mpf_set_prec(x,p) mpfr_round(x,__gmp_default_rounding_mode,p)
+#define mpf_set_prec_raw mpfr_set_prec_raw
+#define mpf_trunc mpfr_trunc
+#define mpf_sgn mpfr_sgn
+#define mpf_swap mpfr_swap
+
+/* functions which take as argument the rounding mode */
+#define mpf_abs(x,y) mpfr_abs(x,y,__gmp_default_rounding_mode)
+#define mpf_add(x,y,z) mpfr_add(x,y,z,__gmp_default_rounding_mode)
+#define mpf_add_ui(x,y,z) \
+ mpfr_add_ui(x,y,z,__gmp_default_rounding_mode)
+#define mpf_div(x,y,z) mpfr_div(x,y,z,__gmp_default_rounding_mode)
+#define mpf_div_ui(x,y,z) \
+ mpfr_div_ui(x,y,z,__gmp_default_rounding_mode)
+#define mpf_div_2exp(x,y,z) \
+ mpfr_div_2exp(x,y,z,__gmp_default_rounding_mode)
+#define mpf_dump(x,y,z) \
+ mpfr_dump(x,y,z,__gmp_default_rounding_mode)
+#define mpf_get_str(x,y,z,t,u) \
+ mpfr_get_str(x,y,z,t,u,__gmp_default_rounding_mode)
+#define mpf_inp_str(x,y,z) mpfr_inp_str(x,y,z,__gmp_default_rounding_mode)
+#define mpf_set_str(x,y,z) mpfr_set_str(x,y,z,__gmp_default_rounding_mode)
+#define mpf_init_set(x,y) mpfr_init_set(x,y,__gmp_default_rounding_mode)
+#define mpf_init_set_d(x,y) mpfr_init_set_d(x,y,__gmp_default_rounding_mode)
+#define mpf_init_set_si(x,y) mpfr_init_set_si(x,y,__gmp_default_rounding_mode)
+#define mpf_init_set_str(x,y,z) mpfr_init_set_str(x,y,z,__gmp_default_rounding_mode)
+#define mpf_init_set_ui(x,y) mpfr_init_set_ui(x,y,__gmp_default_rounding_mode)
+#define mpf_mul(x,y,z) mpfr_mul(x,y,z,__gmp_default_rounding_mode)
+#define mpf_mul_2exp(x,y,z) mpfr_mul_2exp(x,y,z,__gmp_default_rounding_mode)
+#define mpf_mul_ui(x,y,z) mpfr_mul_ui(x,y,z,__gmp_default_rounding_mode)
+#define mpf_neg(x,y) mpfr_neg(x,y,__gmp_default_rounding_mode)
+#define mpf_out_str(x,y,z,t) mpfr_out_str(x,y,z,t,__gmp_default_rounding_mode)
+#define mpf_pow_ui(x,y,z) mpfr_pow_ui(x,y,z,__gmp_default_rounding_mode)
+#define mpf_reldiff(x,y,z) mpfr_reldiff(x,y,z,__gmp_default_rounding_mode)
+#define mpf_set(x,y) mpfr_set(x,y,__gmp_default_rounding_mode)
+#define mpf_set_d(x,y) mpfr_set_d(x,y,__gmp_default_rounding_mode)
+#define mpf_set_q(x,y) mpfr_set_q(x,y,__gmp_default_rounding_mode)
+#define mpf_set_si(x,y) mpfr_set_si(x,y,__gmp_default_rounding_mode)
+#define mpf_set_ui(x,y) mpfr_set_ui(x,y,__gmp_default_rounding_mode)
+#define mpf_set_z(x,y) mpfr_set_z(x,y,__gmp_default_rounding_mode)
+#define mpf_sqrt(x,y) mpfr_sqrt(x,y,__gmp_default_rounding_mode)
+#define mpf_sqrt_ui(x,y) mpfr_sqrt_ui(x,y,__gmp_default_rounding_mode)
+#define mpf_sub(x,y,z) mpfr_sub(x,y,z,__gmp_default_rounding_mode)
+#define mpf_sub_ui(x,y,z) mpfr_sub_ui(x,y,z,__gmp_default_rounding_mode)
+#define mpf_ui_div(x,y,z) mpfr_ui_div(x,y,z,__gmp_default_rounding_mode)
+#define mpf_ui_sub(x,y,z) mpfr_ui_sub(x,y,z,__gmp_default_rounding_mode)
+#define mpf_urandomb(x,y,n) mpfr_urandomb(x,y)
diff --git a/mpfr/mpfr-impl.h b/mpfr/mpfr-impl.h
index 3464febb1..5303b8068 100644
--- a/mpfr/mpfr-impl.h
+++ b/mpfr/mpfr-impl.h
@@ -1,6 +1,6 @@
/* Utilities for MPFR developers, not exported.
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999-2000 Free Software Foundation.
This file is part of the MPFR Library.
@@ -19,40 +19,97 @@ along with the MPFR Library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
-#include <math.h>
-/* generate a random double using the whole range of possible values,
- including denormalized numbers, NaN, infinities, ... */
-double drand()
-{
- volatile double d; int *i;
+/* Fudges */
+#define _mp_allocate_func __gmp_allocate_func
+#define _mp_reallocate_func __gmp_reallocate_func
+#define _mp_free_func __gmp_free_func
+#define _mp_default_allocate __gmp_default_allocate
+#define _mp_default_reallocate __gmp_default_reallocate
+#define _mp_default_free __gmp_default_free
- i = (int*) &d;
- i[0] = mrand48();
- i[1] = mrand48();
- return d;
-}
-/* returns the number of ulp's between a and b */
-int ulp(a,b) double a,b;
-{
- double eps=1.1102230246251565404e-16; /* 2^(-53) */
- if (a==0.0) {
- if (b==0.0) return 0;
- else if (b<0.0) return 2147483647;
- else return -2147483647;
- }
- b = (a-b)/a;
- if (b>0)
- return (int) floor(b/eps);
- else
- return (int) ceil(b/eps);
-}
-/* return double m*2^e */
-double dbl(m,e) double m; int e;
-{
- if (e>=0) while (e-->0) m *= 2.0;
- else while (e++<0) m /= 2.0;
- return m;
+
+
+/* Definition of constants */
+
+#define LOG2 0.69314718055994528622 /* log(2) rounded to zero on 53 bits */
+
+/* macros for doubles, based on gmp union ieee_double_extract */
+
+typedef union ieee_double_extract Ieee_double_extract;
+
+#define DOUBLE_ISNANorINF(x) (((Ieee_double_extract *)&(x))->s.exp == 0x7ff)
+#define DOUBLE_ISINF(x) (DOUBLE_ISNANorINF(x) && \
+ (((Ieee_double_extract *)&(x))->s.manl == 0) && \
+ (((Ieee_double_extract *)&(x))->s.manh == 0))
+#define DOUBLE_ISNAN(x) (DOUBLE_ISNANorINF(x) && \
+ ((((Ieee_double_extract *)&(x))->s.manl != 0) || \
+ (((Ieee_double_extract *)&(x))->s.manh != 0)))
+
+/* bit 31 of _mpfr_size is used for sign,
+ bit 30 of _mpfr_size is used for Nan flag,
+ bit 29 of _mpfr_size is used for Inf flag,
+ remaining bits are used to store the number of allocated limbs */
+#define MPFR_CLEAR_FLAGS(x) (((x) -> _mpfr_size &= ~(3 << 29)))
+#define MPFR_IS_NAN(x) (((x)->_mpfr_size >> 30)&1)
+#define MPFR_SET_NAN(x) ((x)->_mpfr_size |= (1<<30))
+#define MPFR_CLEAR_NAN(x) (((x) -> _mpfr_size &= ~(1 << 30)))
+#define MPFR_IS_INF(x) (((x)->_mpfr_size >> 29)&1)
+#define MPFR_SET_INF(x) ((x)->_mpfr_size |= (1<<29))
+#define MPFR_CLEAR_INF(x) ((x)->_mpfr_size &= ~(1 << 29))
+#define MPFR_IS_FP(x) ((((x) -> _mpfr_size >> 29) & 3) == 0)
+#define MPFR_ABSSIZE(x) ((x)->_mpfr_size & ((1<<29)-1))
+#define MPFR_SIZE(x) ((x)->_mpfr_size)
+#define MPFR_EXP(x) ((x)->_mpfr_exp)
+#define MPFR_MANT(x) ((x)->_mpfr_d)
+#define MPFR_ISNONNEG(x) (MPFR_NOTZERO((x)) && MPFR_SIGN(x)>=0)
+#define MPFR_ISNEG(x) (MPFR_NOTZERO((x)) && MPFR_SIGN(x)==-1)
+#define MPFR_CHANGE_SIGN(x) (MPFR_SIZE(x) ^= (((mp_size_t)1)<<31))
+#define MPFR_SET_SAME_SIGN(x, y) if (MPFR_SIGN((x)) != MPFR_SIGN((y))) { MPFR_CHANGE_SIGN((x)); }
+#define MPFR_PREC(x) ((x)->_mpfr_prec)
+#define MPFR_NOTZERO(x) (MPFR_MANT(x)[(MPFR_PREC(x)-1)/BITS_PER_MP_LIMB])
+#define MPFR_IS_ZERO(x) ((MPFR_NOTZERO(x))==0)
+#define MPFR_SET_ZERO(x) (MPFR_MANT(x)[(MPFR_PREC(x)-1)/BITS_PER_MP_LIMB] = 0)
+#define mpfr_sgn(x) ((MPFR_NOTZERO(x)) ? MPFR_SIGN(x) : 0)
+
+/* Memory gestion */
+
+/* temporary allocate s limbs at xp, and initialize mpfr variable x */
+#define MPFR_INIT(xp, x, p, s) xp = (mp_ptr) TMP_ALLOC(s*BYTES_PER_MP_LIMB); \
+ MPFR_PREC(x) = p; MPFR_MANT(x) = xp; MPFR_SIZE(x) = s; MPFR_EXP(x) = 0;
+/* same when xp is already allocated */
+#define MPFR_INIT1(xp, x, p, s) \
+ MPFR_PREC(x)=p; MPFR_MANT(x)=xp; MPFR_SIZE(x)=s;
+
+#ifndef _PROTO
+#if defined (__STDC__) || defined (__cplusplus)
+#define _PROTO(x) x
+#else
+#define _PROTO(x) ()
+#endif
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+int mpfr_round_raw _PROTO ((mp_limb_t *, mp_limb_t *, mp_prec_t, int,
+ mp_prec_t, mp_rnd_t));
+int mpfr_round_raw2 _PROTO((mp_limb_t *, mp_prec_t, int, mp_rnd_t, mp_prec_t));
+int mpfr_can_round_raw _PROTO ((mp_limb_t *, mp_prec_t, int, mp_prec_t,
+ mp_rnd_t, mp_rnd_t, mp_prec_t));
+double mpfr_get_d2 _PROTO ((mpfr_srcptr, long));
+mp_size_t mpn_sqrtrem_new _PROTO ((mp_limb_t *, mp_limb_t *, mp_limb_t *, mp_size_t));
+int mpfr_cmp2 _PROTO ((mpfr_srcptr, mpfr_srcptr));
+long _mpfr_ceil_log2 _PROTO ((double));
+long _mpfr_floor_log2 _PROTO ((double));
+double _mpfr_ceil_exp2 _PROTO ((double));
+unsigned long _mpfr_isqrt _PROTO ((unsigned long));
+unsigned long _mpfr_cuberoot _PROTO ((unsigned long));
+
+#if defined (__cplusplus)
}
+#endif
+
diff --git a/mpfr/mpfr-test.h b/mpfr/mpfr-test.h
new file mode 100644
index 000000000..ef9fbfb04
--- /dev/null
+++ b/mpfr/mpfr-test.h
@@ -0,0 +1,82 @@
+/* auxiliary functions for MPFR tests.
+
+Copyright (C) 1999-2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <math.h>
+#ifdef __mips
+#include <sys/fpu.h>
+#endif
+
+#if defined (hpux)
+#define srandom srand48
+#define random mrand48
+#endif
+
+double drand _PROTO((void));
+int ulp _PROTO((double, double));
+double dbl _PROTO((double, int));
+
+#define MINNORM 2.2250738585072013831e-308 /* 2^(-1022), smallest normalized */
+#define MAXNORM 1.7976931348623157081e308 /* 2^(1023)*(2-2^(-52)) */
+
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define ABS(x) (((x)>0) ? (x) : (-x))
+
+/* generate a random double using the whole range of possible values,
+ including denormalized numbers, NaN, infinities, ... */
+double drand ()
+{
+ double d; int *i, expo;
+
+ i = (int*) &d;
+ d = 1.0;
+ if (i[0]==0) expo=1; /* little endian, exponent in i[1] */
+ else expo=0;
+ i[0] = lrand48();
+ i[1] = lrand48();
+ while (i[expo]>=2146435072) i[expo] = lrand48(); /* avoids NaNs */
+ if (lrand48()%2 && !isnan(d)) d=-d; /* generates negative numbers */
+ return d;
+}
+
+/* returns the number of ulp's between a and b */
+int ulp (double a, double b)
+{
+ double eps=1.1102230246251565404e-16; /* 2^(-53) */
+ if (a==0.0) {
+ if (b==0.0) return 0;
+ else if (b<0.0) return 2147483647;
+ else return -2147483647;
+ }
+ b = (a-b)/a;
+ if (b>0)
+ return (int) floor(b/eps);
+ else
+ return (int) ceil(b/eps);
+}
+
+/* return double m*2^e */
+double dbl (double m, int e)
+{
+ if (e>=0) while (e-->0) m *= 2.0;
+ else while (e++<0) m /= 2.0;
+ return m;
+}
diff --git a/mpfr/mpfr.h b/mpfr/mpfr.h
index 78034affb..948b1103e 100644
--- a/mpfr/mpfr.h
+++ b/mpfr/mpfr.h
@@ -1,6 +1,6 @@
/* mpfr.h -- Include file for mpfr.
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -21,14 +21,6 @@ MA 02111-1307, USA. */
#include <stdio.h>
-/* Cygnus does not know about *rand48 functions */
-#ifdef __CYGWIN32__
-#define mrand48 rand
-#define drand48 rand
-#define lrand48 rand
-#define srand48 srand
-#endif
-
/* Definition of rounding modes */
#define GMP_RNDN 0
@@ -38,32 +30,35 @@ MA 02111-1307, USA. */
/* Definitions of types and their semantics */
+typedef unsigned long int mp_prec_t; /* easy to change if necessary */
+typedef int mp_rnd_t; /* preferred to char */
+
typedef struct {
- unsigned long int _mp_prec; /* WARNING : for the mpfr type, the precision */
+ mp_prec_t _mpfr_prec; /* WARNING : for the mpfr type, the precision */
/* should be understood as the number of BITS,*/
/* not the number of mp_limb_t's. This means */
/* that the corresponding number of allocated
limbs is >= ceil(_mp_prec/BITS_PER_MP_LIMB) */
- mp_size_t _mp_size; /* abs(_mp_size) is the number of allocated
+ mp_size_t _mpfr_size; /* MPFR_ABSSIZE(.) is the number of allocated
limbs the field _mp_d points to.
- The sign is that of _mp_size.
+ The sign is that of _mpfr_size.
The number 0 is such that _mp_d[k-1]=0
where k = ceil(_mp_prec/BITS_PER_MP_LIMB) */
- mp_exp_t _mp_exp;
- mp_limb_t *_mp_d;
+ mp_exp_t _mpfr_exp;
+ mp_limb_t *_mpfr_d;
}
__mpfr_struct;
/*
The number represented is
- sign(_mp_size)*(_mp_d[k-1]/B+_mp_d[k-2]/B^2+...+_mp_d[0]/B^k)*2^_mp_exp
+ sign(_mpfr_size)*(_mpfr_d[k-1]/B+_mpfr_d[k-2]/B^2+...+_mpfr_d[0]/B^k)*2^_mpfr_exp
where k=ceil(_mp_prec/BITS_PER_MP_LIMB) and B=2^BITS_PER_MP_LIMB.
For the msb (most significant bit) normalized representation, we must have
- _mp_d[k-1]>=B/2, unless the number is zero (in that case its sign is still
- given by sign(_mp_size)).
+ _mpfr_d[k-1]>=B/2, unless the number is zero (in that case its sign is still
+ given by sign(_mpfr_size)).
We must also have the last k*BITS_PER_MP_LIMB-_mp_prec bits set to zero.
*/
@@ -72,6 +67,7 @@ typedef __mpfr_struct mpfr_t[1];
typedef __mpfr_struct *mpfr_ptr;
typedef __gmp_const __mpfr_struct *mpfr_srcptr;
+#define MPFR_SIGN(x) (((x)->_mpfr_size >> 31) ? -1 : 1)
/* Prototypes */
@@ -83,122 +79,100 @@ typedef __gmp_const __mpfr_struct *mpfr_srcptr;
#endif
#endif
-/* bit 31 of _mp_size is used for sign,
- bit 30 of _mp_size is used for Nan flag,
- remaining bits are used to store the number of allocated limbs */
-#define FLAG_NAN(x) (((x)->_mp_size >> 30)&1)
-#define SET_NAN(x) ((x)->_mp_size |= (1<<30))
-#define ABSSIZE(x) ((x)->_mp_size & ((1<<30)-1))
-#define SIZE(x) ((x)->_mp_size)
-#define EXP(x) ((x)->_mp_exp)
-#define MANT(x) ((x)->_mp_d)
-#define SIGN(x) (((x)->_mp_size >> 31) ? -1 : 1)
-#define ISNONNEG(x) (SIGN(x)>=0)
-#define ISNEG(x) (SIGN(x)==-1)
-#define CHANGE_SIGN(x) (SIZE(x) = SIZE(x) ^ (1<<31))
-#define PREC(x) ((x)->_mp_prec)
-#define NOTZERO(x) (MANT(x)[(PREC(x)-1)/BITS_PER_MP_LIMB])
-#define SET_ZERO(x) (MANT(x)[(PREC(x)-1)/BITS_PER_MP_LIMB] = 0)
-
-/* reallocates the mantissa of x to q bits and sets the precision to q */
-#define _mpfr_realloc(x, q) { \
- (x)->_mp_d = (mp_ptr) (*__gmp_reallocate_func) \
- ((x)->_mp_d, (x)->_mp_prec>>3 + 1, (q)>>3 + 1); \
- (x)->_mp_prec = q; }
-
-void mpfr_init2 _PROTO ((mpfr_ptr, unsigned long int));
-int mpfr_round_raw _PROTO ((mp_limb_t *, mp_limb_t *, unsigned long, char,
- unsigned long, char));
-int mpfr_round_raw2 _PROTO ((mp_limb_t *, unsigned long, char, char,
- unsigned long));
-void mpfr_round _PROTO ((mpfr_ptr, char, unsigned long));
-int mpfr_can_round _PROTO ((mpfr_ptr, unsigned long, unsigned char,
- unsigned char, unsigned long));
-int mpfr_can_round_raw _PROTO ((mp_limb_t *, unsigned long, int,
- unsigned long,
- unsigned char, unsigned char, unsigned long));
-void mpfr_set_d _PROTO ((mpfr_ptr, double, unsigned char));
-int mpfr_set_z _PROTO ((mpfr_ptr, mpz_srcptr, unsigned char));
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+void mpfr_init2 _PROTO ((mpfr_ptr, mp_prec_t));
+void mpfr_init _PROTO ((mpfr_ptr));
+void mpfr_round _PROTO ((mpfr_ptr, mp_rnd_t, mp_prec_t));
+int mpfr_can_round _PROTO ((mpfr_ptr, mp_prec_t, mp_rnd_t, mp_rnd_t,
+ mp_prec_t));
+void mpfr_set_d _PROTO ((mpfr_ptr, double, mp_rnd_t));
+int mpfr_set_z _PROTO ((mpfr_ptr, mpz_srcptr, mp_rnd_t));
+mp_exp_t mpz_set_fr _PROTO ((mpz_ptr, mpfr_srcptr));
+void mpfr_set_q _PROTO ((mpfr_ptr, mpq_srcptr, mp_rnd_t));
double mpfr_get_d _PROTO ((mpfr_srcptr));
-double mpfr_get_d2 _PROTO ((mpfr_srcptr, long));
-void mpfr_set_f _PROTO ((mpfr_ptr, mpf_srcptr, char));
-void mpfr_set_si _PROTO ((mpfr_ptr, long, unsigned char));
-void mpfr_set_ui _PROTO ((mpfr_ptr, unsigned long, unsigned char));
+void mpfr_set_f _PROTO ((mpfr_ptr, mpf_srcptr, mp_rnd_t));
+void mpfr_set_si _PROTO ((mpfr_ptr, long, mp_rnd_t));
+void mpfr_set_ui _PROTO ((mpfr_ptr, unsigned long, mp_rnd_t));
void mpfr_print_raw _PROTO ((mpfr_srcptr));
-void mpfr_random _PROTO ((mpfr_ptr));
+void mpfr_random _PROTO ((mpfr_ptr));
+void mpfr_srandom _PROTO ((unsigned long int));
+void mpfr_random2 _PROTO ((mpfr_ptr, mp_size_t, mp_exp_t));
+void mpfr_urandomb _PROTO ((mpfr_ptr, gmp_randstate_t));
void mpfr_clear _PROTO ((mpfr_ptr));
-void mpfr_set_str_raw _PROTO ((mpfr_ptr, char *));
-void mpfr_get_str_raw _PROTO ((char *, mpfr_srcptr));
-char* mpfr_get_str _PROTO ((char *, mp_exp_t *, int, size_t, mpfr_srcptr, unsigned char));
-size_t mpfr_out_str _PROTO ((FILE *, int, size_t, mpfr_srcptr, unsigned char));
-void mpfr_mul _PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, unsigned char));
-void mpfr_pow_ui _PROTO ((mpfr_ptr, mpfr_srcptr, unsigned int, unsigned char));
-void mpfr_ui_pow_ui _PROTO ((mpfr_ptr, unsigned int, unsigned int, unsigned char));
-mp_limb_t mpn_divrem_n _PROTO ((mp_limb_t *, mp_limb_t *, mp_limb_t *, mp_size_t));
-mp_size_t kara_sqrtrem _PROTO ((mp_limb_t *, mp_limb_t *, mp_limb_t *, mp_size_t));
-void mpfr_div _PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, unsigned char));
-void mpfr_agm _PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, unsigned char));
-int mpfr_sqrt _PROTO ((mpfr_ptr, mpfr_srcptr, unsigned char));
-void mpfr_add _PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, unsigned char));
-int mpfr_add_one_ulp _PROTO ((mpfr_ptr));
-void mpfr_sub _PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, unsigned char));
-void mpfr_set4 _PROTO ((mpfr_ptr, mpfr_srcptr, unsigned char, int));
-void mpfr_pi _PROTO ((mpfr_ptr, unsigned char));
-void mpfr_log2 _PROTO ((mpfr_ptr, unsigned char));
-int mpfr_log _PROTO ((mpfr_ptr, mpfr_srcptr, unsigned char));
-int mpfr_exp _PROTO ((mpfr_ptr, mpfr_srcptr, unsigned char));
-int mpfr_zeta _PROTO ((mpfr_ptr, mpfr_srcptr, unsigned char));
-void mpfr_mul_ui _PROTO((mpfr_ptr, mpfr_srcptr, unsigned long, unsigned char));
-void mpfr_set_machine_rnd_mode _PROTO ((unsigned char));
-int mpfr_cmp3 _PROTO ((mpfr_srcptr, mpfr_srcptr, long int));
+void mpfr_set_str_raw _PROTO ((mpfr_ptr, char *));
+int mpfr_set_str _PROTO ((mpfr_ptr, char *, int, mp_rnd_t));
+int mpfr_init_set_str _PROTO ((mpfr_ptr, char *, int, mp_rnd_t));
+size_t mpfr_inp_str _PROTO ((mpfr_ptr, FILE *, int, mp_rnd_t));
+char* mpfr_get_str _PROTO ((char *, mp_exp_t *, int, size_t, mpfr_srcptr, mp_rnd_t));
+size_t mpfr_out_str _PROTO ((FILE *, int, size_t, mpfr_srcptr, mp_rnd_t));
+void mpfr_mul _PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
+int mpfr_pow_ui _PROTO ((mpfr_ptr, mpfr_srcptr, unsigned long int, mp_rnd_t));
+int mpfr_ui_pow_ui _PROTO ((mpfr_ptr, unsigned long int, unsigned long int,
+ mp_rnd_t));
+void mpfr_div _PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
+void mpfr_agm _PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
+int mpfr_sqrt _PROTO ((mpfr_ptr, mpfr_srcptr, mp_rnd_t));
+int mpfr_sqrt_ui _PROTO ((mpfr_ptr, unsigned long, mp_rnd_t));
+void mpfr_add _PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
+void mpfr_add_ui _PROTO ((mpfr_ptr, mpfr_srcptr, unsigned long, mp_rnd_t));
+void mpfr_sub_ui _PROTO ((mpfr_ptr, mpfr_srcptr, unsigned long, mp_rnd_t));
+void mpfr_add_one_ulp _PROTO ((mpfr_ptr));
+void mpfr_sub _PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
+void mpfr_ui_sub _PROTO ((mpfr_ptr, unsigned long, mpfr_srcptr, mp_rnd_t));
+void mpfr_reldiff _PROTO ((mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t));
+void mpfr_const_pi _PROTO ((mpfr_ptr, mp_rnd_t));
+void mpfr_const_log2 _PROTO ((mpfr_ptr, mp_rnd_t));
+int mpfr_log _PROTO ((mpfr_ptr, mpfr_srcptr, mp_rnd_t));
+int mpfr_exp _PROTO ((mpfr_ptr, mpfr_srcptr, mp_rnd_t));
+int mpfr_sin_cos _PROTO ((mpfr_ptr, mpfr_ptr, mpfr_srcptr, mp_rnd_t));
+void mpfr_mul_ui _PROTO((mpfr_ptr, mpfr_srcptr, unsigned long int, mp_rnd_t));
+void mpfr_set_machine_rnd_mode _PROTO ((mp_rnd_t));
int mpfr_cmp_ui_2exp _PROTO ((mpfr_srcptr, unsigned long int, int));
int mpfr_cmp_si_2exp _PROTO ((mpfr_srcptr, long int, int));
-int mpfr_cmp2 _PROTO ((mpfr_srcptr, mpfr_srcptr));
-void mpfr_mul_2exp _PROTO((mpfr_ptr, mpfr_srcptr, unsigned long int,unsigned char));
-void mpfr_div_2exp _PROTO((mpfr_ptr, mpfr_srcptr, unsigned long int,unsigned char));
-void mpfr_set_prec _PROTO((mpfr_ptr, unsigned long int));
-void mpfr_set_default_prec _PROTO((unsigned long int));
-extern mp_size_t __gmp_default_fp_bit_precision;
-extern char __gmp_default_rounding_mode;
-char * mpfr_print_rnd_mode _PROTO((unsigned char));
-void mpfr_neg _PROTO((mpfr_ptr, mpfr_srcptr, unsigned char));
-int mpfr_sub_one_ulp _PROTO((mpfr_ptr x));
-int mpfr_div_ui _PROTO((mpfr_ptr y, mpfr_srcptr x, unsigned long u, unsigned char rnd_mode));
-unsigned long int mpfr_get_prec _PROTO((mpfr_t x));
-
-#define mpfr_init(x) mpfr_init2(x, __gmp_default_fp_bit_precision)
-#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,SIGN(b))
-#define mpfr_cmp(b,c) mpfr_cmp3(b,c,1)
-
-#if (BITS_PER_MP_LIMB==32)
-#define MPFR_LIMBS_PER_DOUBLE 2
-#elif (BITS_PER_MP_LIMB==64)
-#define MPFR_LIMBS_PER_DOUBLE 1
-#endif
-
-/* gmp-2.0.2 had only one threshold for both multiplication and squaring */
-#ifndef KARATSUBA_MUL_THRESHOLD
-#ifdef KARATSUBA_THRESHOLD
-#define KARATSUBA_MUL_THRESHOLD KARATSUBA_THRESHOLD
-#else
-#define KARATSUBA_MUL_THRESHOLD 16
-#endif
-#endif
-
-#define mpfr_init_set_si(x, i, p, rnd) \
- mpfr_init2((x), (p)); mpfr_set_si((x), (i), (rnd));
-#define mpfr_init_set_ui(x, i, p, rnd) \
- mpfr_init2((x), (p)); mpfr_set_ui((x), (i), (rnd));
-#define mpfr_init_set_d(x, d, p, rnd) \
- mpfr_init2((x), (p)); mpfr_set_d((x), (d), (rnd));
-#define mpfr_init_set(x, y, p, rnd) \
- mpfr_init2((x), (p)); mpfr_set((x), (y), (rnd));
-#define mpfr_init_set_f(x, y, p, rnd) \
- mpfr_init2((x), (p)); mpfr_set_f((x), (y), (rnd));
-#define mpfr_init_set_str(x, y, p, rnd) \
- mpfr_init2((x), (p)); mpfr_set_str((x), (y), (rnd));
-#define mpfr_init_set_str_raw(x, y, p, rnd) \
- mpfr_init2((x), (p)); mpfr_set_str_raw((x), (y), (rnd));
+void mpfr_mul_2exp _PROTO((mpfr_ptr, mpfr_srcptr, unsigned long int,mp_rnd_t));
+void mpfr_div_2exp _PROTO((mpfr_ptr, mpfr_srcptr, unsigned long int,mp_rnd_t));
+void mpfr_set_prec _PROTO((mpfr_ptr, mp_prec_t));
+void mpfr_set_prec_raw _PROTO((mpfr_ptr, mp_prec_t));
+void mpfr_set_default_prec _PROTO((mp_prec_t));
+extern mp_prec_t __gmp_default_fp_bit_precision;
+extern mp_rnd_t __gmp_default_rounding_mode;
+char * mpfr_print_rnd_mode _PROTO((mp_rnd_t));
+void mpfr_neg _PROTO((mpfr_ptr, mpfr_srcptr, mp_rnd_t));
+void mpfr_sub_one_ulp _PROTO((mpfr_ptr));
+int mpfr_div_ui _PROTO((mpfr_ptr, mpfr_srcptr, unsigned long int, mp_rnd_t));
+void mpfr_ui_div _PROTO((mpfr_ptr, unsigned long int, mpfr_srcptr, mp_rnd_t));
+mp_prec_t mpfr_get_prec _PROTO((mpfr_srcptr));
+void mpfr_set_default_rounding_mode _PROTO((mp_rnd_t));
+int mpfr_eq _PROTO((mpfr_srcptr, mpfr_srcptr, unsigned long));
+void mpfr_floor _PROTO((mpfr_ptr, mpfr_srcptr));
+void mpfr_trunc _PROTO((mpfr_ptr, mpfr_srcptr));
+void mpfr_ceil _PROTO((mpfr_ptr, mpfr_srcptr));
+void mpfr_extract _PROTO((mpz_ptr, mpfr_srcptr, unsigned int));
+void mpfr_swap _PROTO((mpfr_ptr, mpfr_ptr));
+void mpfr_dump _PROTO((mpfr_srcptr, mp_rnd_t));
+void mpfr_set4 _PROTO ((mpfr_ptr, mpfr_srcptr, mp_rnd_t, int));
+int mpfr_cmp3 _PROTO ((mpfr_srcptr, mpfr_srcptr, long int));
+#if defined (__cplusplus)
+}
+#endif
+
+#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))
+#define mpfr_abs(a,b,r) mpfr_set4(a,b,r,1)
+#define mpfr_cmp(b, c) mpfr_cmp3(b, c, 1)
+
+#define mpfr_init_set_si(x, i, rnd) \
+ do { mpfr_init(x); mpfr_set_si((x), (i), (rnd)); } while (0)
+#define mpfr_init_set_ui(x, i, rnd) \
+ do { mpfr_init(x); mpfr_set_ui((x), (i), (rnd)); } while (0)
+#define mpfr_init_set_d(x, d, rnd) \
+ do { mpfr_init(x); mpfr_set_d((x), (d), (rnd)); } while (0)
+#define mpfr_init_set(x, y, rnd) \
+ do { mpfr_init(x); mpfr_set((x), (y), (rnd)); } while (0)
+#define mpfr_init_set_f(x, y, rnd) \
+ do { mpfr_init(x); mpfr_set_f((x), (y), (rnd)); } while (0)
diff --git a/mpfr/mpz_set_fr.c b/mpfr/mpz_set_fr.c
new file mode 100644
index 000000000..92f14f17d
--- /dev/null
+++ b/mpfr/mpz_set_fr.c
@@ -0,0 +1,63 @@
+/* mpz_set_fr -- set a multiple-precision integer from a floating-point number
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+/* puts the mantissa of f into z, and returns 'exp' such that f = z * 2^exp
+ */
+mp_exp_t
+#if __STDC__
+mpz_set_fr (mpz_ptr z, mpfr_srcptr f)
+#else
+mpz_set_fr (z, f)
+ mpz_ptr z;
+ mpfr_srcptr f;
+#endif
+{
+ int fn, sh;
+
+ /* TODO: semantique de INF, NAN dans ce contexte ; lever une FPE ? */
+
+ fn = 1 + (MPFR_PREC(f)-1)/BITS_PER_MP_LIMB;
+
+ /* check whether allocated space for z is enough */
+ if (ALLOC(z) < fn) {
+ PTR(z) = (mp_ptr) (*_mp_reallocate_func) (PTR(z),
+ ABS(SIZ(z))*BYTES_PER_MP_LIMB, fn*BYTES_PER_MP_LIMB);
+ if (PTR(z) == NULL) {
+ fprintf (stderr, "Error in mpz_set_fr: no more memory available\n");
+ exit (1);
+ }
+ ALLOC(z) = fn;
+ }
+
+ sh = fn*BITS_PER_MP_LIMB - MPFR_PREC(f);
+ if (sh) mpn_rshift(PTR(z), MPFR_MANT(f), fn, sh);
+ else MPN_COPY(PTR(z), MPFR_MANT(f), fn);
+
+ SIZ(z) = fn;
+
+ return MPFR_EXP(f)-MPFR_PREC(f);
+}
diff --git a/mpfr/mul.c b/mpfr/mul.c
index c7c3cd3f5..945bd35ec 100644
--- a/mpfr/mul.c
+++ b/mpfr/mul.c
@@ -1,6 +1,6 @@
/* mpfr_mul -- multiply two floating-point numbers
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -23,36 +23,61 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
/* Remains to do:
-- do not use all bits of b and c when PREC(b)>PREC(a) or PREC(c)>PREC(a)
- [current complexity is O(PREC(b)*PREC(c))]
+- do not use all bits of b and c when MPFR_PREC(b)>MPFR_PREC(a) or MPFR_PREC(c)>MPFR_PREC(a)
+ [current complexity is O(MPFR_PREC(b)*MPFR_PREC(c))]
*/
void
#if __STDC__
-mpfr_mul(mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, unsigned char rnd_mode)
+mpfr_mul(mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mp_rnd_t rnd_mode)
#else
mpfr_mul(a, b, c, rnd_mode)
- mpfr_ptr a;
- mpfr_srcptr b;
- mpfr_srcptr c;
- unsigned char rnd_mode;
+ mpfr_ptr a;
+ mpfr_srcptr b;
+ mpfr_srcptr c;
+ mp_rnd_t rnd_mode;
#endif
{
unsigned int bn, cn, an, tn, k; int cc;
- mp_limb_t *ap=MANT(a), *bp=MANT(b), *cp=MANT(c), *tmp, b1;
+ mp_limb_t *ap=MPFR_MANT(a), *bp=MPFR_MANT(b), *cp=MPFR_MANT(c), *tmp, b1;
long int sign_product;
TMP_DECL(marker);
/* deal with NaN and zero */
- if (FLAG_NAN(b) || FLAG_NAN(c)) { SET_NAN(a); return; }
- if (!NOTZERO(b) || !NOTZERO(c)) { SET_ZERO(a); return; }
+ if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c))
+ { MPFR_CLEAR_FLAGS(a); MPFR_SET_NAN(a); return; }
+ if (MPFR_IS_INF(b))
+ {
+ if (!MPFR_NOTZERO(c)) { MPFR_CLEAR_FLAGS(a); MPFR_SET_NAN(a); return; }
+ else
+ {
+ if (MPFR_SIGN(a) != MPFR_SIGN(b) * MPFR_SIGN(c)) MPFR_CHANGE_SIGN(a);
+ MPFR_CLEAR_FLAGS(a);
+ MPFR_SET_INF(a); return;
+ }
+ }
+ else if (MPFR_IS_INF(c))
+ {
+ if (!MPFR_NOTZERO(b)) { MPFR_CLEAR_FLAGS(a); MPFR_SET_NAN(a); return; }
+ else
+ {
+ if (MPFR_SIGN(a) != MPFR_SIGN(b) * MPFR_SIGN(c)) MPFR_CHANGE_SIGN(a);
+ MPFR_CLEAR_FLAGS(a); MPFR_SET_INF(a); return;
+ }
+ }
- sign_product = SIGN(b) * SIGN(c);
- bn = (PREC(b)-1)/mp_bits_per_limb+1; /* number of significant limbs of b */
- cn = (PREC(c)-1)/mp_bits_per_limb+1; /* number of significant limbs of c */
- tn = (PREC(c)+PREC(b)-1)/mp_bits_per_limb+1;
+ if (!MPFR_NOTZERO(b) || !MPFR_NOTZERO(c))
+ { MPFR_CLEAR_FLAGS(a); MPFR_SET_ZERO(a); return; }
+
+ sign_product = MPFR_SIGN(b) * MPFR_SIGN(c);
+
+ MPFR_CLEAR_FLAGS(a);
+ bn = (MPFR_PREC(b)-1)/BITS_PER_MP_LIMB+1; /* number of significant limbs of b */
+ cn = (MPFR_PREC(c)-1)/BITS_PER_MP_LIMB+1; /* number of significant limbs of c */
+ tn = (MPFR_PREC(c)+MPFR_PREC(b)-1)/BITS_PER_MP_LIMB+1;
k = bn+cn; /* effective nb of limbs used by b*c */
TMP_MARK(marker);
tmp = (mp_limb_t*) TMP_ALLOC(k*BYTES_PER_MP_LIMB);
@@ -61,18 +86,18 @@ mpfr_mul(a, b, c, rnd_mode)
b1 = (bn>=cn) ? mpn_mul(tmp, bp, bn, cp, cn) : mpn_mul(tmp, cp, cn, bp, bn);
/* now tmp[0]..tmp[k-1] contains the product of both mantissa,
- with tmp[k-1]>=2^(mp_bits_per_limb-2) */
- an = (PREC(a)-1)/mp_bits_per_limb+1; /* number of significant limbs of a */
- b1 >>= mp_bits_per_limb-1; /* msb from the product */
+ with tmp[k-1]>=2^(BITS_PER_MP_LIMB-2) */
+ an = (MPFR_PREC(a)-1)/BITS_PER_MP_LIMB+1; /* number of significant limbs of a */
+ b1 >>= BITS_PER_MP_LIMB-1; /* msb from the product */
if (b1==0) mpn_lshift(tmp, tmp, k, 1);
cc = mpfr_round_raw(ap, tmp+bn+cn-tn,
- PREC(b)+PREC(c), (sign_product<0), PREC(a), rnd_mode);
+ MPFR_PREC(b)+MPFR_PREC(c), (sign_product<0), MPFR_PREC(a), rnd_mode);
if (cc) { /* cc = 1 ==> result is a power of two */
ap[an-1] = (mp_limb_t) 1 << (BITS_PER_MP_LIMB-1);
}
- EXP(a) = EXP(b) + EXP(c) + b1 - 1 + cc;
- if (sign_product * SIGN(a)<0) CHANGE_SIGN(a);
+ MPFR_EXP(a) = MPFR_EXP(b) + MPFR_EXP(c) + b1 - 1 + cc;
+ if (sign_product * MPFR_SIGN(a)<0) MPFR_CHANGE_SIGN(a);
TMP_FREE(marker);
return;
}
diff --git a/mpfr/mul_2exp.c b/mpfr/mul_2exp.c
index 31dab2ac6..e1d030751 100644
--- a/mpfr/mul_2exp.c
+++ b/mpfr/mul_2exp.c
@@ -1,6 +1,6 @@
/* mpfr_mul_2exp -- multiply a floating-point number by a power of two
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -23,21 +23,22 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
void
#if __STDC__
-mpfr_mul_2exp(mpfr_ptr y, mpfr_srcptr x, unsigned long int n, unsigned char rnd_mode)
+mpfr_mul_2exp(mpfr_ptr y, mpfr_srcptr x, unsigned long int n, mp_rnd_t rnd_mode)
#else
mpfr_mul_2exp(y, x, n, rnd_mode)
mpfr_ptr y;
mpfr_srcptr x;
- unsigned long int n;
- unsigned char rnd_mode;
+ unsigned long int n;
+ mp_rnd_t rnd_mode;
#endif
{
/* Important particular case */
if (y != x) mpfr_set(y, x, rnd_mode);
- EXP(y) += n;
+ MPFR_EXP(y) += n;
return;
}
diff --git a/mpfr/mul_ui.c b/mpfr/mul_ui.c
index 83981a83c..e92a79155 100644
--- a/mpfr/mul_ui.c
+++ b/mpfr/mul_ui.c
@@ -1,6 +1,6 @@
/* mpfr_mul_ui -- multiply a floating-point number by a machine integer
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -24,46 +24,96 @@ MA 02111-1307, USA. */
#include "gmp-impl.h"
#include "longlong.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
void
#if __STDC__
-mpfr_mul_ui(mpfr_ptr y, mpfr_srcptr x, unsigned long u, unsigned char RND_MODE)
+mpfr_mul_ui(mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mp_rnd_t rnd_mode)
#else
-mpfr_mul_ui(y, x, u, RND_MODE)
- mpfr_ptr y;
- mpfr_srcptr x;
- unsigned long u;
- unsigned char RND_MODE;
+mpfr_mul_ui(y, x, u, rnd_mode)
+ mpfr_ptr y;
+ mpfr_srcptr x;
+ unsigned long int u;
+ mp_rnd_t rnd_mode;
#endif
{
- mp_limb_t carry, *my, *old_my; unsigned long c;
- unsigned long xsize, ysize, cnt, dif;
+ mp_limb_t carry, *my, *old_my, *my2; unsigned long c;
+ unsigned long xsize, ysize, cnt, dif, ex, sh;
TMP_DECL(marker);
+ if (MPFR_IS_NAN(x))
+ {
+ MPFR_CLEAR_FLAGS(y);
+ MPFR_SET_NAN(y);
+ return;
+ }
+
+ if (MPFR_IS_INF(x))
+ {
+ MPFR_CLEAR_FLAGS(y);
+ if (u)
+ {
+ MPFR_SET_INF(y);
+ if (MPFR_SIGN(y) != MPFR_SIGN(x)) { MPFR_CHANGE_SIGN(y); }
+ return;
+ }
+ else { MPFR_SET_NAN(y); return; }
+ }
+
+ MPFR_CLEAR_FLAGS(y);
+
TMP_MARK(marker);
- my = MANT(y);
- ysize = (PREC(y)-1)/BITS_PER_MP_LIMB + 1;
- xsize = (PREC(x)-1)/BITS_PER_MP_LIMB + 1;
+ my = MPFR_MANT(y); ex = MPFR_EXP(x);
+ ysize = (MPFR_PREC(y)-1)/BITS_PER_MP_LIMB + 1;
+ xsize = (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB + 1;
+
+ old_my = my;
if (ysize < xsize) {
- old_my = my;
my = (mp_ptr) TMP_ALLOC (xsize * BYTES_PER_MP_LIMB);
dif=0;
}
else dif=ysize-xsize;
- carry = mpn_mul_1(my+dif, MANT(x), xsize, u);
+ carry = mpn_mul_1(my+dif, MPFR_MANT(x), xsize, u);
MPN_ZERO(my, dif);
/* WARNING: count_leading_zeros is undefined for carry=0 */
if (carry) count_leading_zeros(cnt, carry);
else cnt=BITS_PER_MP_LIMB;
-
- c = mpfr_round_raw(my, my, PREC(x), (SIGN(x)<0),
- PREC(y)-BITS_PER_MP_LIMB+cnt, RND_MODE);
-
+
+ /* Warning: the number of limbs used by x and the lower part
+ of y may differ */
+ sh = (MPFR_PREC(x)+BITS_PER_MP_LIMB-1)/BITS_PER_MP_LIMB
+ - (MPFR_PREC(y)+cnt-1)/BITS_PER_MP_LIMB;
+
+ /* Warning: if all significant bits are in the carry, one has to
+ be careful */
+ if (cnt + MPFR_PREC(y) < BITS_PER_MP_LIMB)
+ {
+ /* Quick 'n dirty */
+
+ if (xsize > ysize) {
+ my2 = (mp_ptr) TMP_ALLOC ((xsize + 1) * BYTES_PER_MP_LIMB);
+ my2[xsize] = mpn_lshift(my2, my, xsize, cnt)
+ | (carry << (cnt ? BITS_PER_MP_LIMB - cnt : 0));
+ }
+ else {
+ my2 = (mp_ptr) TMP_ALLOC ((ysize + 1) * BYTES_PER_MP_LIMB);
+ my2[ysize] = mpn_lshift(my2, my, ysize, cnt)
+ | (carry << (cnt ? BITS_PER_MP_LIMB - cnt : 0));
+ }
+
+ my = my2; ex += BITS_PER_MP_LIMB - cnt;
+ carry = 0; cnt = BITS_PER_MP_LIMB;
+ }
+
+ c = mpfr_round_raw(my+sh, my, MPFR_PREC(x), (MPFR_SIGN(x)<0),
+ MPFR_PREC(y)-BITS_PER_MP_LIMB+cnt, rnd_mode);
+
/* If cnt = 1111111111111 and c = 1 we shall get depressed */
- if (c && (carry == (((mp_limb_t)1) << (BITS_PER_MP_LIMB - cnt)) - 1))
+ if (c && (carry == (((mp_limb_t)1) << (cnt ? BITS_PER_MP_LIMB - cnt : 0))
+ - 1))
{
cnt--;
mpn_rshift(my, my, ysize, BITS_PER_MP_LIMB - cnt);
@@ -76,9 +126,9 @@ mpfr_mul_ui(y, x, u, RND_MODE)
mpn_rshift(my, my, ysize, BITS_PER_MP_LIMB - cnt);
my[ysize - 1] |= (carry << cnt);
}
- EXP(y) = EXP(x) + BITS_PER_MP_LIMB - cnt;
+ MPFR_EXP(y) = ex + BITS_PER_MP_LIMB - cnt;
if (ysize < xsize) MPN_COPY(old_my, my, ysize);
/* set sign */
- if (SIGN(y) != SIGN(x)) CHANGE_SIGN(y);
+ if (MPFR_SIGN(y) * MPFR_SIGN(x) < 0) MPFR_CHANGE_SIGN(y);
TMP_FREE(marker);
}
diff --git a/mpfr/neg.c b/mpfr/neg.c
index fff73a65a..b67e0c9d2 100644
--- a/mpfr/neg.c
+++ b/mpfr/neg.c
@@ -1,6 +1,6 @@
/* mpfr_neg -- change the sign of a floating-point number
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -21,20 +21,20 @@ MA 02111-1307, USA. */
#include <stdio.h>
#include "gmp.h"
-#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
void
#if __STDC__
-mpfr_neg(mpfr_ptr a, mpfr_srcptr b, unsigned char rnd_mode)
+mpfr_neg (mpfr_ptr a, mpfr_srcptr b, mp_rnd_t rnd_mode)
#else
-mpfr_neg(a, b, rnd_mode)
- mpfr_ptr a;
- mpfr_srcptr b;
- unsigned char rnd_mode;
+mpfr_neg (a, b, rnd_mode)
+ mpfr_ptr a;
+ mpfr_srcptr b;
+ mp_rnd_t rnd_mode;
#endif
{
- if (a != b) mpfr_set4(a, b, rnd_mode, -SIGN(b));
- else CHANGE_SIGN(a);
+ if (a != b) mpfr_set4(a, b, rnd_mode, -MPFR_SIGN(b));
+ else MPFR_CHANGE_SIGN(a);
return;
}
diff --git a/mpfr/out_str.c b/mpfr/out_str.c
index d6221776b..9b7d7408b 100644
--- a/mpfr/out_str.c
+++ b/mpfr/out_str.c
@@ -1,6 +1,6 @@
/* mpfr_out_str -- output a floating-point number to a stream
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -20,30 +20,37 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include <stdio.h>
-#include <math.h>
+#include <string.h>
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
size_t
#if __STDC__
mpfr_out_str (FILE *stream, int base, size_t n_digits, mpfr_srcptr op,
- unsigned char rnd_mode)
+ mp_rnd_t rnd_mode)
#else
mpfr_out_str (stream, base, n_digits, op, rnd_mode)
- FILE *stream;
+ FILE *stream;
int base;
- size_t n_digits;
- mpfr_srcptr op;
- unsigned char rnd_mode;
+ size_t n_digits;
+ mpfr_srcptr op;
+ mp_rnd_t rnd_mode;
#endif
{
char *s,*s0; size_t l; mp_exp_t e;
- if (FLAG_NAN(op)) { fprintf(stream, "NaN"); return 3; }
- if (!NOTZERO(op)) { fprintf(stream, "0"); return 1; }
+ if (MPFR_IS_NAN(op)) { fprintf(stream, "NaN"); return 3; }
+ if (!MPFR_NOTZERO(op)) { fprintf(stream, "0"); return 1; }
+ if (MPFR_IS_INF(op))
+ {
+ if (MPFR_SIGN(op) == 1) { fprintf(stream, "Inf"); return 3; }
+ else { fprintf(stream, "-Inf"); return 4; }
+ }
s = mpfr_get_str(NULL, &e, base, n_digits, op, rnd_mode);
+ /* TODO: maintenir le code pour les infinis dans get_str ? */
s0 = s;
/* for op=3.1416 we have s = "31416" and e = 1 */
@@ -60,6 +67,6 @@ mpfr_out_str (stream, base, n_digits, op, rnd_mode)
fprintf(stream, "%s", s);
}
- (*__gmp_free_func)(s0, l);
+ (*_mp_free_func)(s0, l);
return l;
}
diff --git a/mpfr/pi.c b/mpfr/pi.c
index 322a2ab1c..54b0d3f84 100644
--- a/mpfr/pi.c
+++ b/mpfr/pi.c
@@ -1,6 +1,6 @@
-/* mpfr_pi -- compute Pi
+/* mpfr_const_pi -- compute Pi
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -20,14 +20,111 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include <stdio.h>
-#include <math.h>
#include "gmp.h"
#include "gmp-impl.h"
#include "longlong.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
+
+int mpfr_aux_pi (mpfr_ptr, mpz_srcptr, int, int);
+int mpfr_pi_machin3 (mpfr_ptr, mp_rnd_t);
+
+#define A
+#define A1 1
+#define A2 2
+#undef B
+#define C
+#define C1 3
+#define C2 2
+#define GENERIC mpfr_aux_pi
+#define R_IS_RATIONAL
+#define NO_FACTORIAL
+#include "generic.c"
+
+
+int
+#if __STDC__
+mpfr_pi_machin3 (mpfr_ptr mylog, mp_rnd_t rnd_mode)
+#else
+mpfr_pi_machin3 (mylog, rnd_mode)
+ mpfr_ptr mylog;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ int prec, logn, prec_x;
+ int prec_i_want=MPFR_PREC(mylog);
+ int good = 0;
+ mpfr_t tmp1, tmp2, result,tmp3,tmp4,tmp5,tmp6;
+ mpz_t cst;
+
+ MPFR_CLEAR_FLAGS(mylog);
+ logn = _mpfr_ceil_log2 ((double) MPFR_PREC(mylog));
+ prec_x = prec_i_want + logn + 5;
+ mpz_init(cst);
+ while (!good){
+ prec = _mpfr_ceil_log2 ((double) prec_x);
+
+ mpfr_init2(tmp1, prec_x);
+ mpfr_init2(tmp2, prec_x);
+ mpfr_init2(tmp3, prec_x);
+ mpfr_init2(tmp4, prec_x);
+ mpfr_init2(tmp5, prec_x);
+ mpfr_init2(tmp6, prec_x);
+ mpfr_init2(result, prec_x);
+ mpz_set_si(cst, -1);
+
+ mpfr_aux_pi(tmp1, cst, 268*268, prec - 4);
+ mpfr_div_ui(tmp1, tmp1, 268, GMP_RNDD);
+ mpfr_mul_ui(tmp1, tmp1, 61, GMP_RNDD);
+
+ mpfr_aux_pi(tmp2, cst, 343*343, prec - 4);
+ mpfr_div_ui(tmp2, tmp2, 343, GMP_RNDD);
+ mpfr_mul_ui(tmp2, tmp2, 122, GMP_RNDD);
+
+ mpfr_aux_pi(tmp3, cst, 557*557, prec - 4);
+ mpfr_div_ui(tmp3, tmp3, 557, GMP_RNDD);
+ mpfr_mul_ui(tmp3, tmp3, 115, GMP_RNDD);
+
+ mpfr_aux_pi(tmp4, cst, 1068*1068, prec - 4);
+ mpfr_div_ui(tmp4, tmp4, 1068, GMP_RNDD);
+ mpfr_mul_ui(tmp4, tmp4, 32, GMP_RNDD);
+
+ mpfr_aux_pi(tmp5, cst, 3458*3458, prec - 4);
+ mpfr_div_ui(tmp5, tmp5, 3458, GMP_RNDD);
+ mpfr_mul_ui(tmp5, tmp5, 83, GMP_RNDD);
+
+ mpfr_aux_pi(tmp6, cst, 27493*27493, prec - 4);
+ mpfr_div_ui(tmp6, tmp6, 27493, GMP_RNDD);
+ mpfr_mul_ui(tmp6, tmp6, 44, GMP_RNDD);
+
+ mpfr_add(result, tmp1, tmp2, GMP_RNDD);
+ mpfr_add(result, result, tmp3, GMP_RNDD);
+ mpfr_sub(result, result, tmp4, GMP_RNDD);
+ mpfr_add(result, result, tmp5, GMP_RNDD);
+ mpfr_add(result, result, tmp6, GMP_RNDD);
+ mpfr_mul_2exp(result, result, 2, GMP_RNDD);
+ mpfr_clear(tmp1);
+ mpfr_clear(tmp2);
+ mpfr_clear(tmp3);
+ mpfr_clear(tmp4);
+ mpfr_clear(tmp5);
+ mpfr_clear(tmp6);
+ if (mpfr_can_round(result, prec_x - 5, GMP_RNDD, rnd_mode, prec_i_want)){
+ mpfr_set(mylog, result, rnd_mode);
+ mpfr_clear(result);
+ good = 1;
+ } else
+ {
+ mpfr_clear(result);
+ prec_x += logn;
+ }
+ }
+ mpz_clear(cst);
+ return 0;
+}
/*
-Set x to the value of Pi to precision PREC(x) rounded to direction rnd_mode.
+Set x to the value of Pi to precision MPFR_PREC(x) rounded to direction rnd_mode.
Use the formula giving the binary representation of Pi found by Simon Plouffe
and the Borwein's brothers:
@@ -56,76 +153,79 @@ S(N)-S'(N) <= sum(1, n=0..N-1) = N
so Pi*16^N-S'(N) <= N+1 (as 1/4/N^2 < 1)
*/
-mpfr_t __mpfr_pi; /* stored value of Pi */
-int __mpfr_pi_prec=0; /* precision of stored value */
-char __mpfr_pi_rnd; /* rounding mode of stored value */
+mpfr_t __mpfr_const_pi; /* stored value of Pi */
+int __mpfr_const_pi_prec=0; /* precision of stored value */
+mp_rnd_t __mpfr_const_pi_rnd; /* rounding mode of stored value */
void
#if __STDC__
-mpfr_pi(mpfr_ptr x, unsigned char rnd_mode)
+mpfr_const_pi(mpfr_ptr x, mp_rnd_t rnd_mode)
#else
-mpfr_pi(x, rnd_mode)
- mpfr_ptr x;
- unsigned char rnd_mode;
+mpfr_const_pi(x, rnd_mode)
+ mpfr_ptr x;
+ mp_rnd_t rnd_mode;
#endif
{
int N, oldN, n, prec; mpz_t pi, num, den, d3, d2, tmp; mpfr_t y;
- prec=PREC(x);
+ prec=MPFR_PREC(x);
/* has stored value enough precision ? */
- if ((prec==__mpfr_pi_prec && rnd_mode==__mpfr_pi_rnd) ||
- (prec<=__mpfr_pi_prec &&
- mpfr_can_round(__mpfr_pi, __mpfr_pi_prec, __mpfr_pi_rnd, rnd_mode, prec)))
+ if ((prec==__mpfr_const_pi_prec && rnd_mode==__mpfr_const_pi_rnd) ||
+ (prec<=__mpfr_const_pi_prec &&
+ mpfr_can_round(__mpfr_const_pi, __mpfr_const_pi_prec,
+ __mpfr_const_pi_rnd, rnd_mode, prec)))
{
- mpfr_set(x, __mpfr_pi, rnd_mode); return;
+ mpfr_set(x, __mpfr_const_pi, rnd_mode); return;
}
- /* need to recompute */
- N=1;
- do {
- oldN = N;
- N = (prec+3)/4 + (int)ceil(log((double)N+1.0)/log(2.0));
- } while (N != oldN);
- mpz_init(pi); mpz_init(num); mpz_init(den); mpz_init(d3); mpz_init(d2);
- mpz_init(tmp);
- mpz_set_ui(pi, 0);
- mpz_set_ui(num, 16); /* num(-1) */
- mpz_set_ui(den, 21); /* den(-1) */
- mpz_set_si(d3, -2454);
- mpz_set_ui(d2, 14736);
+ if (prec < 20000){
+ /* need to recompute */
+ N=1;
+ do {
+ oldN = N;
+ N = (prec+3)/4 + _mpfr_ceil_log2((double) N + 1.0);
+ } while (N != oldN);
+ mpz_init(pi); mpz_init(num); mpz_init(den); mpz_init(d3); mpz_init(d2);
+ mpz_init(tmp);
+ mpz_set_ui(pi, 0);
+ mpz_set_ui(num, 16); /* num(-1) */
+ mpz_set_ui(den, 21); /* den(-1) */
+ mpz_set_si(d3, -2454);
+ mpz_set_ui(d2, 14736);
/* invariants: num=120*n^2+151*n+47, den=512*n^4+1024*n^3+712*n^2+194*n+15
- d3 = 2048*n^3+400*n-6, d2 = 6144*n^2-6144*n+2448
+ d3 = 2048*n^3+400*n-6, d2 = 6144*n^2-6144*n+2448
*/
- for (n=0; n<N; n++) {
- /* num(n)-num(n-1) = 240*n+31 */
- mpz_add_ui(num, num, 240*n+31); /* no overflow up to PREC=71M */
- /* d2(n) - d2(n-1) = 12288*(n-1) */
- if (n>0) mpz_add_ui(d2, d2, 12288*(n-1));
- else mpz_sub_ui(d2, d2, 12288);
- /* d3(n) - d3(n-1) = d2 */
- mpz_add(d3, d3, d2);
- /* den(n)-den(n-1) = 2048*n^3 + 400n - 6 = d3 */
- mpz_add(den, den, d3);
- mpz_mul_2exp(tmp, num, 4*(N-n));
- mpz_fdiv_q(tmp, tmp, den);
- mpz_add(pi, pi, tmp);
- }
- mpfr_set_z(x, pi, rnd_mode);
- mpfr_init2(y, mpfr_get_prec(x));
- mpz_add_ui(pi, pi, N+1);
- mpfr_set_z(y, pi, rnd_mode);
- if (mpfr_cmp(x, y) != 0) {
- fprintf(stderr, "does not converge\n"); exit(1);
- }
- EXP(x) -= 4*N;
- mpz_clear(pi); mpz_clear(num); mpz_clear(den); mpz_clear(d3); mpz_clear(d2);
- mpz_clear(tmp); mpfr_clear(y);
-
+ for (n=0; n<N; n++) {
+ /* num(n)-num(n-1) = 240*n+31 */
+ mpz_add_ui(num, num, 240*n+31); /* no overflow up to MPFR_PREC=71M */
+ /* d2(n) - d2(n-1) = 12288*(n-1) */
+ if (n>0) mpz_add_ui(d2, d2, 12288*(n-1));
+ else mpz_sub_ui(d2, d2, 12288);
+ /* d3(n) - d3(n-1) = d2 */
+ mpz_add(d3, d3, d2);
+ /* den(n)-den(n-1) = 2048*n^3 + 400n - 6 = d3 */
+ mpz_add(den, den, d3);
+ mpz_mul_2exp(tmp, num, 4*(N-n));
+ mpz_fdiv_q(tmp, tmp, den);
+ mpz_add(pi, pi, tmp);
+ }
+ mpfr_set_z(x, pi, rnd_mode);
+ mpfr_init2(y, mpfr_get_prec(x));
+ mpz_add_ui(pi, pi, N+1);
+ mpfr_set_z(y, pi, rnd_mode);
+ if (mpfr_cmp(x, y) != 0) {
+ fprintf(stderr, "does not converge\n"); exit(1);
+ }
+ MPFR_EXP(x) -= 4*N;
+ mpz_clear(pi); mpz_clear(num); mpz_clear(den); mpz_clear(d3); mpz_clear(d2);
+ mpz_clear(tmp); mpfr_clear(y);
+ } else
+ mpfr_pi_machin3(x, rnd_mode);
/* store computed value */
- if (__mpfr_pi_prec==0) mpfr_init2(__mpfr_pi, prec);
- else mpfr_set_prec(__mpfr_pi, prec);
- mpfr_set(__mpfr_pi, x, rnd_mode);
- __mpfr_pi_prec=prec;
- __mpfr_pi_rnd=rnd_mode;
+ if (__mpfr_const_pi_prec==0) mpfr_init2(__mpfr_const_pi, prec);
+ else mpfr_set_prec(__mpfr_const_pi, prec);
+ mpfr_set(__mpfr_const_pi, x, rnd_mode);
+ __mpfr_const_pi_prec=prec;
+ __mpfr_const_pi_rnd=rnd_mode;
}
diff --git a/mpfr/pow.c b/mpfr/pow.c
index c53819ec2..3032c5d72 100644
--- a/mpfr/pow.c
+++ b/mpfr/pow.c
@@ -1,7 +1,7 @@
/* mpfr_pow_ui, mpfr_ui_pow_ui -- compute the power of a floating-point
number or machine integer
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -23,45 +23,99 @@ MA 02111-1307, USA. */
#include <stdio.h>
#include "gmp.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
-/* sets x to y^n */
-void
+/* sets x to y^n, and returns ceil(log2(max ulp error)) */
+int
#if __STDC__
-mpfr_pow_ui (mpfr_ptr x, mpfr_srcptr y, unsigned int n, unsigned char rnd)
+mpfr_pow_ui (mpfr_ptr x, mpfr_srcptr y, unsigned long int n, mp_rnd_t rnd)
#else
mpfr_pow_ui (x, y, n, rnd)
mpfr_ptr x;
- mpfr_srcptr y;
- unsigned int n;
- unsigned char rnd;
+ mpfr_srcptr y;
+ unsigned long int n;
+ mp_rnd_t rnd;
#endif
{
- int i;
+ long int i;
+ unsigned long m;
+ double err;
+ mpfr_t ycopy;
+
+ if (MPFR_IS_NAN(y)) { MPFR_SET_NAN(x); return 0; }
+
+ MPFR_CLEAR_NAN(x);
+
+ if (MPFR_IS_INF(y))
+ {
+ if (n == 0) { MPFR_SET_NAN(x); return 0; }
+ /* Inf^n = Inf, (-Inf)^n = Inf for n even, -Inf for n odd */
+ else if ((MPFR_SIGN(y) < 0) && (n % 2 == 1)) {
+ if (MPFR_SIGN(x) > 0) MPFR_CHANGE_SIGN(x);
+ }
+ else if (MPFR_SIGN(x) < 0)
+ MPFR_CHANGE_SIGN(x);
+ MPFR_SET_INF(x); return 0;
+ }
- if (n==0) { mpfr_set_ui(x, 1, rnd); return; }
+ MPFR_CLEAR_INF(x);
+
+ if (n==0) { mpfr_set_ui(x, 1, rnd); return 0; }
+
+ if (x == y) {
+ mpfr_init2 (ycopy, MPFR_PREC(y));
+ mpfr_set (ycopy, y, GMP_RNDN); /* exact */
+ }
+
mpfr_set(x, y, rnd);
- for (i=0;(1<<i)<=n;i++);
+ err = 1.0;
+ for (m=n, i=0; m; i++, m>>=1);
/* now 2^(i-1) <= n < 2^i */
for (i-=2; i>=0; i--) {
- mpfr_mul(x, x, x, rnd);
- if (n & (1<<i)) mpfr_mul(x, x, y, rnd);
+ mpfr_mul(x, x, x, rnd); err = 2.0*err+1.0;
+ if (n & (1<<i)) {
+ mpfr_mul(x, x, (x == y) ? ycopy : y, rnd);
+ err += 1.0;
+ }
}
- return;
+
+ if (x == y) mpfr_clear (ycopy);
+ return _mpfr_ceil_log2 (err);
}
-/* sets x to y^n */
-void mpfr_ui_pow_ui (mpfr_ptr x, unsigned int y, unsigned int n,
- unsigned char rnd)
+/* sets x to y^n, and returns ceil(log2(max ulp error)) */
+
+/* TODO: gerer l'infini en cas de debordement ? Fait mecaniquement si fait
+ dans mul ? */
+
+int
+#if __STDC__
+mpfr_ui_pow_ui (mpfr_ptr x, unsigned long int y, unsigned long int n,
+ mp_rnd_t rnd)
+#else
+mpfr_ui_pow_ui (x, y, n, rnd)
+ mpfr_ptr x;
+ unsigned long int y;
+ unsigned long int n;
+ mp_rnd_t rnd;
+#endif
{
- int i;
+ long int i; double err;
+
+ MPFR_CLEAR_FLAGS(x);
+ if (n==0) { mpfr_set_ui(x, 1, rnd); return 0; }
- if (n==0) { mpfr_set_ui(x, 1, rnd); return; }
mpfr_set_ui(x, y, rnd);
+ err = 1.0;
+
for (i=0;(1<<i)<=n;i++);
/* now 2^(i-1) <= n < 2^i */
for (i-=2; i>=0; i--) {
- mpfr_mul(x, x, x, rnd);
- if (n & (1<<i)) mpfr_mul_ui(x, x, y, rnd);
+ mpfr_mul(x, x, x, rnd); err = 2.0 * err + 1.0;
+ if (n & (1<<i)) {
+ mpfr_mul_ui(x, x, y, rnd);
+ err = err + 1.0;
+ }
}
- return;
+ return _mpfr_ceil_log2 (err);
}
diff --git a/mpfr/print_raw.c b/mpfr/print_raw.c
index 4ff68bcaf..69e682757 100644
--- a/mpfr/print_raw.c
+++ b/mpfr/print_raw.c
@@ -1,7 +1,7 @@
/* mpfr_print_raw -- print the internal binary representation of a
floating-point number
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -24,26 +24,31 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
+
+void mpfr_get_str_raw (char *, mpfr_srcptr);
void
#if __STDC__
-mpfr_get_str_raw(char *digit_ptr, mpfr_srcptr x)
+mpfr_get_str_raw (char *digit_ptr, mpfr_srcptr x)
#else
-mpfr_get_str_raw(digit_ptr, x)
+mpfr_get_str_raw (digit_ptr, x)
char *digit_ptr;
mpfr_srcptr x;
#endif
{
mp_limb_t *mx, wd, t; long ex, sx, k, l, p;
- mx = MANT(x);
- ex = EXP(x);
- p = PREC(x);
+ mx = MPFR_MANT(x);
+ ex = MPFR_EXP(x);
+ p = MPFR_PREC(x);
+
+ /* TODO: utilite de gerer l'infini a ce niveau ? */
- if (SIGN(x) < 0) { *digit_ptr = '-'; digit_ptr++; }
+ if (MPFR_SIGN(x) < 0) { *digit_ptr = '-'; digit_ptr++; }
sprintf(digit_ptr, "0."); digit_ptr += 2;
- sx = 1+(p-1)/mp_bits_per_limb; /* number of significant limbs */
+ sx = 1+(p-1)/BITS_PER_MP_LIMB; /* number of significant limbs */
for (k = sx - 1; k >= 0 ; k--)
{
wd = mx[k];
@@ -69,23 +74,35 @@ mpfr_print_raw(x)
mpfr_srcptr x;
#endif
{
- char *str;
+ char *str;
+ unsigned long alloc_size;
- if (FLAG_NAN(x)) printf("NaN");
- else if (!NOTZERO(x)) printf("0");
+ if (MPFR_IS_NAN(x)) printf("NaN");
+ else if (MPFR_IS_INF(x)) {
+ if (MPFR_SIGN(x) == 1) { printf("Inf"); } else printf("-Inf");
+ }
+ else if (!MPFR_NOTZERO(x)) {
+ if (MPFR_SIGN(x) < 0) printf("-");
+ printf("0");
+ }
else {
/* 3 char for sign + 0 + binary point
- + ABSSIZE(x) * BITS_PER_MP_LIMB for mantissa
+ + MPFR_ABSSIZE(x) * BITS_PER_MP_LIMB for mantissa
+ 2 for brackets in mantissa
+ 1 for 'E'
+ 11 for exponent (including sign)
- = 17 + ABSSIZE(x) * BITS_PER_MP_LIMB
+ = 17 + MPFR_ABSSIZE(x) * BITS_PER_MP_LIMB
*/
- str = (char *) malloc((17 + ABSSIZE(x) * BITS_PER_MP_LIMB)*sizeof(char));
+ alloc_size = 17 + MPFR_ABSSIZE(x) * BITS_PER_MP_LIMB;
+ str = (char *) (*_mp_allocate_func) (alloc_size * sizeof(char));
+ if (str == NULL) {
+ fprintf (stderr, "Error in mpfr_print_raw: no more memory available\n");
+ exit (1);
+ }
mpfr_get_str_raw(str, x);
printf("%s", str);
- free(str);
+ (*_mp_free_func) (str, alloc_size * sizeof(char));
}
}
diff --git a/mpfr/print_rnd_mode.c b/mpfr/print_rnd_mode.c
index a7bc1d06d..e97d74eba 100644
--- a/mpfr/print_rnd_mode.c
+++ b/mpfr/print_rnd_mode.c
@@ -1,6 +1,6 @@
/* mpfr_print_rnd_mode -- convert a given rounding mode to a string
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -21,15 +21,15 @@ MA 02111-1307, USA. */
#include <stdio.h>
#include "gmp.h"
-#include "gmp-impl.h"
#include "mpfr.h"
+#include "gmp-impl.h"
char *
#if __STDC__
-mpfr_print_rnd_mode(unsigned char rnd_mode)
+mpfr_print_rnd_mode(mp_rnd_t rnd_mode)
#else
mpfr_print_rnd_mode(rnd_mode)
- unsigned char rnd_mode;
+ mp_rnd_t rnd_mode;
#endif
{
switch (rnd_mode)
@@ -38,6 +38,6 @@ mpfr_print_rnd_mode(rnd_mode)
case GMP_RNDU: return("GMP_RNDU");
case GMP_RNDN: return("GMP_RNDN");
case GMP_RNDZ: return("GMP_RNDZ");
- default: return("unknown rounding mode");
+ default: fprintf(stderr, "unknown rounding mode\n"); exit(1);
}
}
diff --git a/mpfr/random.c b/mpfr/random.c
index e61ddc0b7..e2a50770b 100644
--- a/mpfr/random.c
+++ b/mpfr/random.c
@@ -1,6 +1,6 @@
/* mpfr_random -- generate a random floating-point number
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -24,51 +24,47 @@ MA 02111-1307, USA. */
#include "gmp-impl.h"
#include "longlong.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
-/* Computes a random mpfr in [0, 1[ with precision PREC */
-
-extern long random _PROTO((void));
-extern int srandom _PROTO((unsigned int));
-
-/* extracted from GNU mpf */
-#if defined (__hpux) || defined (__alpha)
-/* HPUX lacks random(). DEC OSF/1 1.2 random() returns a double. */
-#define random mrand48
-#define srandom srand48
-#endif
+/* Computes a random mpfr in [0, 1[ with precision MPFR_PREC */
void
#if __STDC__
-mpfr_random(mpfr_ptr x)
+mpfr_random (mpfr_ptr x)
#else
-mpfr_random(x)
+mpfr_random (x)
mpfr_ptr x;
#endif
{
- mp_limb_t *xp; unsigned long xn, i, cnt, prec=PREC(x);
+ mp_limb_t *xp; unsigned long xn, cnt, prec = MPFR_PREC(x);
- xp = MANT(x);
+ MPFR_CLEAR_FLAGS(x);
+ xp = MPFR_MANT(x);
xn = (prec-1)/BITS_PER_MP_LIMB + 1;
- for (i = 0; i < xn; i++)
- {
- /* random() c/sh/ould be replaced by a homemade random number generator.
- Indeed, if on Linux random is a good RNG, this is definitely not
- the case in most Un*xes. */
- xp[i] = random();
- }
-
- count_leading_zeros(cnt, xp[xn - 1]);
- if (cnt) mpn_lshift(xp, xp, xn, cnt);
- EXP(x) = -cnt;
+ mpn_random (xp, xn);
+
+ if (xp[xn - 1] == 0) xp[xn - 1] = 1;
+ /* since count_leading_zeros doesn't like zeroes */
+
+ count_leading_zeros (cnt, xp[xn - 1]);
+ if (cnt) mpn_lshift (xp, xp, xn, cnt);
+ MPFR_EXP(x) = -cnt;
cnt = xn*BITS_PER_MP_LIMB - prec;
/* cnt is the number of non significant bits in the low limb */
- xp[0] &= ~((((mp_limb_t)1)<<cnt) - 1);
+ xp[0] &= ~((((mp_limb_t) 1) << cnt) - 1);
}
+#if HAVE_SRANDOM
void
-mpfr_srandom(unsigned long seed)
+#if __STDC__
+mpfr_srandom (unsigned long int seed)
+#else
+mpfr_srandom (seed)
+ unsigned long int seed;
+#endif
{
- srandom(seed);
+ srandom (seed);
}
+#endif
diff --git a/mpfr/random2.c b/mpfr/random2.c
new file mode 100644
index 000000000..f3384d0f4
--- /dev/null
+++ b/mpfr/random2.c
@@ -0,0 +1,69 @@
+/* mpf_random2 -- Generate a positive random mpf_t of specified size, with
+ long runs of consecutive ones and zeros in the binary representation.
+ Intended for testing of other MP routines.
+
+Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+void
+#if __STDC__
+mpfr_random2 (mpfr_ptr x, mp_size_t size, mp_exp_t exp)
+#else
+mpfr_random2 (x, size, exp)
+ mpfr_ptr x;
+ mp_size_t size;
+ mp_exp_t exp;
+#endif
+{
+ mp_size_t xn;
+ unsigned long cnt;
+ mp_ptr xp = MPFR_MANT(x), yp[1];
+ mp_size_t prec = (MPFR_PREC(x) - 1)/BITS_PER_MP_LIMB;
+
+ MPFR_CLEAR_FLAGS(x);
+ xn = ABS (size);
+ if (xn != 0)
+ {
+ if (xn > prec + 1)
+ xn = prec + 1;
+
+ mpn_random2 (xp, xn);
+ }
+
+ if (exp != 0) {
+ /* use mpn_random instead of random since that function is not
+ available on all platforms (for example HPUX, DEC OSF, ...) */
+ mpn_random ((mp_limb_t*) yp, 1);
+ exp = (mp_exp_t) yp[0] % (2 * exp) - exp;
+ }
+
+ count_leading_zeros(cnt, xp[xn - 1]);
+ if (cnt) mpn_lshift(xp, xp, xn, cnt);
+ MPFR_EXP(x) = exp-cnt;
+ cnt = xn*BITS_PER_MP_LIMB - prec;
+ /* cnt is the number of non significant bits in the low limb */
+ xp[0] &= ~((((mp_limb_t)1)<<cnt) - 1);
+}
diff --git a/mpfr/reldiff.c b/mpfr/reldiff.c
new file mode 100644
index 000000000..ea21a60b1
--- /dev/null
+++ b/mpfr/reldiff.c
@@ -0,0 +1,76 @@
+/* mpfr_reldiff -- compute relative difference of two floating-point numbers.
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+/* reldiff(b, c) = abs(b-c)/b */
+void
+#if __STDC__
+mpfr_reldiff(mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mp_rnd_t rnd_mode)
+#else
+mpfr_reldiff(a, b, c, rnd_mode)
+ mpfr_ptr a;
+ mpfr_srcptr b;
+ mpfr_srcptr c;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ mpfr_t b_copy;
+
+ if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c))
+ { MPFR_CLEAR_FLAGS(a); MPFR_SET_NAN(a); return; }
+ if (MPFR_IS_INF(b))
+ {
+ if (MPFR_IS_INF(c) && (MPFR_SIGN(c) == MPFR_SIGN(b)))
+ { MPFR_CLEAR_FLAGS(a); MPFR_SET_ZERO(a); return; }
+ else
+ { MPFR_CLEAR_FLAGS(a); MPFR_SET_NAN(a); return; }
+ }
+
+ if (MPFR_IS_INF(c))
+ {
+ MPFR_SET_SAME_SIGN(a, b);
+ MPFR_CLEAR_FLAGS(a);
+ MPFR_SET_INF(a);
+ return;
+ }
+
+ if (MPFR_IS_ZERO(b)) /* reldiff = abs(c)/c = sign(c) */
+ /* TODO: faire preciser la SEMANTIQUE DE CE FOUTOIR. */
+ mpfr_set_ui(a, MPFR_SIGN(c), rnd_mode);
+ else {
+ if (a == b) {
+ mpfr_init2 (b_copy, MPFR_PREC(b));
+ mpfr_set (b_copy, b, GMP_RNDN);
+ }
+
+ mpfr_sub(a, b, c, rnd_mode);
+ mpfr_abs(a, a, rnd_mode); /* for compatibility with MPF */
+ mpfr_div(a, a, (a == b) ? b_copy : b, rnd_mode);
+
+ if (a == b) mpfr_clear (b_copy);
+ }
+}
+
diff --git a/mpfr/rnd_mode.c b/mpfr/rnd_mode.c
index 9c37fb4c1..dda40b5b4 100644
--- a/mpfr/rnd_mode.c
+++ b/mpfr/rnd_mode.c
@@ -1,6 +1,6 @@
/* mpfr_set_machine_rnd_mode -- set the rounding mode for machine floats
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -19,6 +19,7 @@ along with the MPFR Library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
+#ifdef TEST
#include <stdio.h>
#include "gmp.h"
#include "mpfr.h"
@@ -30,24 +31,28 @@ MA 02111-1307, USA. */
#define TOZERO fesetround(FE_TOWARDZERO)
#define TOINFP fesetround(FE_UPWARD)
#define TOINFM fesetround(FE_DOWNWARD)
-#elif IRIX64
+#elif __mips
#include <sys/fpu.h>
extern int swapRM();
#define TOZERO swapRM(ROUND_TO_ZERO)
#define TOINFP swapRM(ROUND_TO_PLUS_INFINITY)
#define TONEAREST swapRM(ROUND_TO_NEAREST)
#define TOINFM swapRM(ROUND_TO_MINUS_INFINITY)
-#elif (defined (solaris) || defined (sun4) || defined(hpux))
+#elif (defined (__sparc__) || defined(hpux) || defined(freebsd))
#ifdef hpux
#include <math.h>
#else
+#ifdef freebsd
+#include <floatingpoint.h>
+#else
#include <ieeefp.h>
#endif
+#endif
#define TOZERO fpsetround(FP_RZ)
#define TOINFP fpsetround(FP_RP)
#define TONEAREST fpsetround(FP_RN)
#define TOINFM fpsetround(FP_RM)
-#elif alpha
+#elif defined (__alpha)
#ifdef __GNUC__
/* GCC patched include files forget to define those... */
#define FP_RND_RZ 0
@@ -61,6 +66,11 @@ extern int swapRM();
#define TONEAREST write_rnd(FP_RND_RN)
#define TOINFM write_rnd(FP_RND_RM)
#elif AIX
+/* those values should be defined in float.h but strangely are not */
+#define FP_RND_RZ 0
+#define FP_RND_RN 1
+#define FP_RND_RP 2
+#define FP_RND_RM 3
#include <float.h>
#define TOZERO fp_swap_rnd(FP_RND_RZ)
#define TOINFP fp_swap_rnd(FP_RND_RP)
@@ -73,6 +83,12 @@ char *out;
#define TOINFP ieee_flags("set","direction","positive",&out)
#define TONEAREST ieee_flags("set","direction","nearest",&out)
#define TOINFM ieee_flags("set","direction","negative",&out)
+#elif (defined (__powerpc__) && defined(linux))
+#include <fpu_control.h>
+#define TOZERO _FPU_SETCW(_FPU_RC_ZERO)
+#define TOINFP _FPU_SETCW(_FPU_RC_UP)
+#define TOINFM _FPU_SETCW(_FPU_RC_DOWN)
+#define TONEAREST _FPU_SETCW(_FPU_RC_NEAREST)
#elif (defined (__i386__) || defined (__i486__) || defined (linux))
#ifdef __CYGWIN32__ /* no fpu_control.h under Cygnus */
#define _FPU_EXTENDED 0x300
@@ -101,10 +117,10 @@ char *out;
/* sets the machine rounding mode to the value rnd_mode */
void
#if __STDC__
-mpfr_set_machine_rnd_mode(unsigned char rnd_mode)
+mpfr_set_machine_rnd_mode(mp_rnd_t rnd_mode)
#else
mpfr_set_machine_rnd_mode(rnd_mode)
- unsigned char rnd_mode;
+ mp_rnd_t rnd_mode;
#endif
{
switch (rnd_mode) {
@@ -112,7 +128,7 @@ mpfr_set_machine_rnd_mode(rnd_mode)
case GMP_RNDZ: TOZERO; break;
case GMP_RNDU: TOINFP; break;
case GMP_RNDD: TOINFM; break;
- default: fprintf(stderr,"invalid rounding mode\n"); exit(1);
+ default: fprintf(stderr, "invalid rounding mode\n"); exit(1);
}
}
-
+#endif
diff --git a/mpfr/round.c b/mpfr/round.c
index 99e0e699b..06de436b9 100644
--- a/mpfr/round.c
+++ b/mpfr/round.c
@@ -1,7 +1,7 @@
/* mpfr_round_raw2, mpfr_round_raw, mpfr_round, mpfr_can_round,
mpfr_can_round_raw -- various rounding functions
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -24,10 +24,7 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
-
-#ifdef Exp
-#include "longlong.h"
-#endif
+#include "mpfr-impl.h"
/* returns 0 if round(sign*xp[0..xn-1], prec, rnd) =
round(sign*xp[0..xn-1], prec, GMP_RNDZ), 1 otherwise,
@@ -37,25 +34,28 @@ MA 02111-1307, USA. */
*/
int
#if __STDC__
-mpfr_round_raw2(mp_limb_t *xp, unsigned long xn,
- char neg, char rnd, unsigned long prec)
+mpfr_round_raw2(mp_limb_t *xp, mp_prec_t xn,
+ int neg, mp_rnd_t rnd, mp_prec_t prec)
#else
mpfr_round_raw2(xp, xn, neg, rnd, prec)
mp_limb_t *xp;
- unsigned long xn;
- char neg;
- char rnd;
- unsigned long prec;
+ mp_prec_t xn;
+ int neg;
+ mp_rnd_t rnd;
+ mp_prec_t prec;
#endif
{
- unsigned long nw; long wd; char rw; short l; mp_limb_t mask;
+ mp_prec_t nw; long wd; char rw; short l; mp_limb_t mask;
nw = prec / BITS_PER_MP_LIMB; rw = prec & (BITS_PER_MP_LIMB - 1);
if (rw) nw++;
if (rnd==GMP_RNDZ || xn<nw || (rnd==GMP_RNDU && neg)
|| (rnd==GMP_RNDD && neg==0)) return 0;
- mask = ~((((mp_limb_t)1)<<(BITS_PER_MP_LIMB - rw)) - 1);
+ if (rw)
+ mask = ~((((mp_limb_t)1)<<(BITS_PER_MP_LIMB - rw)) - 1);
+ else mask = ~((mp_limb_t)0);
+
switch (rnd)
{
case GMP_RNDU:
@@ -108,39 +108,36 @@ mpfr_round_raw2(xp, xn, neg, rnd, prec)
}
/* puts in y the value of xp (with precision xprec and sign 1 if negative=0,
- -1 otherwise) rounded to precision yprec and direction RND_MODE
+ -1 otherwise) rounded to precision yprec and direction rnd_mode
Supposes x is not zero nor NaN nor +/- Infinity (i.e. *xp != 0).
*/
int
#if __STDC__
-mpfr_round_raw(mp_limb_t *y, mp_limb_t *xp, unsigned long xprec, char negative,
- unsigned long yprec, char RND_MODE)
+mpfr_round_raw(mp_limb_t *y, mp_limb_t *xp, mp_prec_t xprec, int negative,
+ mp_prec_t yprec, mp_rnd_t rnd_mode)
#else
-mpfr_round_raw(y, xp, xprec, negative, yprec, RND_MODE)
+mpfr_round_raw(y, xp, xprec, negative, yprec, rnd_mode)
mp_limb_t *y;
mp_limb_t *xp;
- unsigned long xprec;
+ mp_prec_t xprec;
char negative;
- unsigned long yprec;
- char RND_MODE;
+ mp_prec_t yprec;
+ mp_rnd_t rnd_mode;
#endif
{
- unsigned long nw, xsize; mp_limb_t mask;
- char rw, xrw, carry = 0;
+ mp_prec_t nw, xsize; mp_limb_t mask;
+ char rw, carry = 0;
xsize = (xprec-1)/BITS_PER_MP_LIMB + 1;
- xrw = xprec % BITS_PER_MP_LIMB; if (xrw == 0) { xrw = BITS_PER_MP_LIMB; }
-
-#ifdef Exp
- count_leading_zeros(flag, xp[xsize-1]);
- yprec += flag;
-#endif
nw = yprec / BITS_PER_MP_LIMB; rw = yprec & (BITS_PER_MP_LIMB - 1);
if (rw) nw++;
/* number of words needed to represent x */
- mask = ~((((mp_limb_t)1)<<(BITS_PER_MP_LIMB - rw)) - (mp_limb_t)1);
+ if (rw)
+ mask = ~((((mp_limb_t)1)<<(BITS_PER_MP_LIMB - rw)) - (mp_limb_t)1);
+ else
+ mask = ~((mp_limb_t)0);
/* precision is larger than the size of x. No rounding is necessary.
Just add zeroes at the end */
@@ -151,9 +148,15 @@ mpfr_round_raw(y, xp, xprec, negative, yprec, RND_MODE)
return 0;
}
- if (mpfr_round_raw2(xp, xsize, negative, RND_MODE, yprec))
- carry = mpn_add_1(y, xp + xsize - nw, nw,
- ((mp_limb_t)1) << (BITS_PER_MP_LIMB - rw));
+ if (mpfr_round_raw2(xp, xsize, negative, rnd_mode, yprec))
+ {
+ if (rw)
+ carry = mpn_add_1(y, xp + xsize - nw, nw,
+ ((mp_limb_t)1) << (BITS_PER_MP_LIMB - rw));
+ else
+ carry = mpn_add_1(y, xp + xsize - nw, nw, 1);
+ }
+
else MPN_COPY(y, xp + xsize - nw, nw);
y[0] &= mask;
@@ -162,34 +165,50 @@ mpfr_round_raw(y, xp, xprec, negative, yprec, RND_MODE)
void
#if __STDC__
-mpfr_round(mpfr_t x, char RND_MODE, unsigned long prec)
+mpfr_round(mpfr_ptr x, mp_rnd_t rnd_mode, mp_prec_t prec)
#else
-mpfr_round(x, RND_MODE, prec)
- mpfr_t x;
- char RND_MODE;
- unsigned long prec;
+mpfr_round(x, rnd_mode, prec)
+ mpfr_ptr x;
+ mp_rnd_t rnd_mode;
+ mp_prec_t prec;
#endif
{
- mp_limb_t *tmp; int carry; unsigned long nw;
- TMP_DECL(marker);
+ mp_limb_t *tmp; int carry, signx; mp_prec_t nw;
+ TMP_DECL(marker);
+ if (MPFR_IS_INF(x) || MPFR_IS_NAN(x)) return;
nw = prec / BITS_PER_MP_LIMB;
if (prec & (BITS_PER_MP_LIMB - 1)) nw++;
+ signx = MPFR_SIGN(x);
+
+ /* check if x has enough allocated space for the mantissa */
+ if (nw > MPFR_ABSSIZE(x)) {
+ MPFR_MANT(x) = (mp_ptr) (*_mp_reallocate_func)
+ (MPFR_MANT(x), MPFR_ABSSIZE(x)*BYTES_PER_MP_LIMB, nw * BYTES_PER_MP_LIMB);
+ if (MPFR_MANT(x) == NULL) {
+ fprintf (stderr, "Error in mpfr_round: no more memory available\n");
+ exit (1);
+ }
+ MPFR_SIZE(x) = nw; /* new number of allocated limbs */
+ }
+
TMP_MARK(marker);
tmp = TMP_ALLOC (nw * BYTES_PER_MP_LIMB);
- carry = mpfr_round_raw(tmp, MANT(x), PREC(x), (SIGN(x)<0), prec, RND_MODE);
+ carry = mpfr_round_raw(tmp, MPFR_MANT(x), MPFR_PREC(x), (MPFR_SIGN(x)<0), prec,
+ rnd_mode);
if (carry)
{
mpn_rshift(tmp, tmp, nw, 1);
tmp [nw-1] |= (((mp_limb_t)1) << (BITS_PER_MP_LIMB - 1));
- EXP(x)++;
+ MPFR_EXP(x)++;
}
- if (SIGN(x)<0) { SIZE(x)=nw; CHANGE_SIGN(x); } else SIZE(x)=nw;
- PREC(x) = prec;
- MPN_COPY(MANT(x), tmp, nw);
- TMP_FREE(marker);
+ MPFR_SIZE(x)=nw;
+ if (signx * MPFR_SIGN(x)<0) MPFR_CHANGE_SIGN(x);
+ MPFR_PREC(x) = prec;
+ MPN_COPY(MPFR_MANT(x), tmp, nw);
+ TMP_FREE(marker);
}
/* hypotheses : BITS_PER_MP_LIMB est une puissance de 2
@@ -197,7 +216,7 @@ mpfr_round(x, RND_MODE, prec)
/* assuming b is an approximation of x in direction rnd1
- with error at most 2^(EXP(b)-err), returns 1 if one is
+ with error at most 2^(MPFR_EXP(b)-err), returns 1 if one is
able to round exactly x to precision prec with direction rnd2,
and 0 otherwise.
@@ -206,35 +225,34 @@ mpfr_round(x, RND_MODE, prec)
int
#if __STDC__
-mpfr_can_round(mpfr_t b, unsigned long err, unsigned char rnd1,
- unsigned char rnd2, unsigned long prec)
+mpfr_can_round(mpfr_ptr b, mp_prec_t err, mp_rnd_t rnd1,
+ mp_rnd_t rnd2, mp_prec_t prec)
#else
mpfr_can_round(b, err, rnd1, rnd2, prec)
- mpfr_t b;
- unsigned long err;
- unsigned char rnd1;
- unsigned char rnd2;
- unsigned long prec;
+ mpfr_ptr b;
+ mp_prec_t err;
+ mp_rnd_t rnd1;
+ mp_rnd_t rnd2;
+ mp_prec_t prec;
#endif
{
- return mpfr_can_round_raw(MANT(b), (PREC(b) - 1)/BITS_PER_MP_LIMB + 1,
- SIGN(b), err, rnd1, rnd2, prec);
+ return mpfr_can_round_raw(MPFR_MANT(b), (MPFR_PREC(b) - 1)/BITS_PER_MP_LIMB + 1,
+ MPFR_SIGN(b), err, rnd1, rnd2, prec);
}
int
#if __STDC__
-mpfr_can_round_raw(mp_limb_t *bp, unsigned long bn, int neg,
- unsigned long err, unsigned char rnd1, unsigned char rnd2,
- unsigned long prec)
+mpfr_can_round_raw(mp_limb_t *bp, mp_prec_t bn, int neg, mp_prec_t err,
+ mp_rnd_t rnd1, mp_rnd_t rnd2, mp_prec_t prec)
#else
mpfr_can_round_raw(bp, bn, neg, err, rnd1, rnd2, prec)
mp_limb_t *bp;
- unsigned long bn;
+ mp_prec_t bn;
int neg;
- unsigned long err;
- unsigned char rnd1;
- unsigned char rnd2;
- unsigned long prec;
+ mp_prec_t err;
+ mp_rnd_t rnd1;
+ mp_rnd_t rnd2;
+ mp_prec_t prec;
#endif
{
int k, k1, l, l1, tn; mp_limb_t cc, cc2, *tmp;
@@ -266,12 +284,12 @@ mpfr_can_round_raw(bp, bn, neg, err, rnd1, rnd2, prec)
switch (rnd1) {
- case GMP_RNDZ: /* b <= x <= b+2^(EXP(b)-err) */
+ case GMP_RNDZ: /* b <= x <= b+2^(MPFR_EXP(b)-err) */
tmp = TMP_ALLOC(tn*BYTES_PER_MP_LIMB);
cc = (bp[bn-1]>>l1) & 1;
cc ^= mpfr_round_raw2(bp, bn, neg, rnd2, prec);
- /* now round b+2^(EXP(b)-err) */
+ /* now round b+2^(MPFR_EXP(b)-err) */
cc2 = mpn_add_1(tmp+bn-k, bp+bn-k, k, (mp_limb_t)1<<l);
/* if carry, then all bits up to err were to 1, and we can round only
if cc==0 and mpfr_round_raw2 returns 0 below */
@@ -282,13 +300,13 @@ mpfr_can_round_raw(bp, bn, neg, err, rnd1, rnd2, prec)
TMP_FREE(marker);
return (cc == cc2);
- case GMP_RNDU: /* b-2^(EXP(b)-err) <= x <= b */
+ case GMP_RNDU: /* b-2^(MPFR_EXP(b)-err) <= x <= b */
tmp = TMP_ALLOC(tn*BYTES_PER_MP_LIMB);
/* first round b */
cc = (bp[bn-1]>>l1) & 1;
cc ^= mpfr_round_raw2(bp, bn, neg, rnd2, prec);
- /* now round b-2^(EXP(b)-err) */
+ /* now round b-2^(MPFR_EXP(b)-err) */
cc2 = mpn_sub_1(tmp+bn-k, bp+bn-k, k, (mp_limb_t)1<<l);
/* if borrow, then all bits up to err were to 0, and we can round only
if cc==0 and mpfr_round_raw2 returns 1 below */
@@ -299,12 +317,12 @@ mpfr_can_round_raw(bp, bn, neg, err, rnd1, rnd2, prec)
TMP_FREE(marker);
return (cc == cc2);
- case GMP_RNDN: /* b-2^(EXP(b)-err-1) <= x <= b+2^(EXP(b)-err-1) */
+ case GMP_RNDN: /* b-2^(MPFR_EXP(b)-err-1) <= x <= b+2^(MPFR_EXP(b)-err-1) */
if (l==0) tn++;
tmp = TMP_ALLOC(tn*BYTES_PER_MP_LIMB);
/* this case is the same than GMP_RNDZ, except we first have to
- subtract 2^(EXP(b)-err-1) from b */
+ subtract 2^(MPFR_EXP(b)-err-1) from b */
if (l) {
l--; /* tn=bn */
@@ -316,14 +334,14 @@ mpfr_can_round_raw(bp, bn, neg, err, rnd1, rnd2, prec)
mpn_sub_1(tmp+tn-k, tmp+tn-k, k, (mp_limb_t)1<<l);
}
- /* round b-2^(EXP(b)-err-1) */
+ /* round b-2^(MPFR_EXP(b)-err-1) */
/* we can disregard borrow, since we start from tmp in 2nd case too */
cc = (tmp[tn-1]>>l1) & 1;
cc ^= mpfr_round_raw2(tmp, tn, neg, rnd2, prec);
if (l==BITS_PER_MP_LIMB-1) { l=0; k--; } else l++;
- /* round b+2^(EXP(b)-err-1) = b-2^(EXP(b)-err-1) + 2^(EXP(b)-err) */
+ /* round b+2^(MPFR_EXP(b)-err-1) = b-2^(MPFR_EXP(b)-err-1) + 2^(MPFR_EXP(b)-err) */
cc2 = mpn_add_1(tmp+tn-k, tmp+tn-k, k, (mp_limb_t)1<<l);
/* if carry, then all bits up to err were to 1, and we can round only
if cc==0 and mpfr_round_raw2 returns 0 below */
diff --git a/mpfr/set.c b/mpfr/set.c
index 7177925fa..9544d6d51 100644
--- a/mpfr/set.c
+++ b/mpfr/set.c
@@ -1,6 +1,6 @@
/* mpfr_set -- copy of a floating-point number
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -23,22 +23,34 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
void
#if __STDC__
-mpfr_set4(mpfr_ptr a, mpfr_srcptr b, unsigned char rnd_mode, int signb)
+mpfr_set4 (mpfr_ptr a, mpfr_srcptr b, mp_rnd_t rnd_mode, int signb)
#else
-mpfr_set4(a, b, rnd_mode, signb)
+mpfr_set4 (a, b, rnd_mode, signb)
mpfr_ptr a;
mpfr_srcptr b;
- unsigned char rnd_mode;
+ mp_rnd_t rnd_mode;
int signb;
#endif
{
- int carry, an, preca = PREC(a), sh; mp_limb_t *ap = MANT(a);
+ int carry, an, preca = MPFR_PREC(a), sh; mp_limb_t *ap = MPFR_MANT(a);
- carry = mpfr_round_raw(ap, MANT(b), PREC(b), (signb<0), preca, rnd_mode);
- EXP(a) = EXP(b);
+ if (MPFR_IS_NAN(b))
+ { MPFR_CLEAR_FLAGS(a); MPFR_SET_NAN(a); return; }
+ if (MPFR_IS_INF(b))
+ {
+ MPFR_CLEAR_FLAGS(a);
+ MPFR_SET_INF(a);
+ if (MPFR_SIGN(a) * signb < 0) MPFR_CHANGE_SIGN(a);
+ return;
+ }
+ MPFR_CLEAR_FLAGS(a);
+
+ carry = mpfr_round_raw(ap, MPFR_MANT(b), MPFR_PREC(b), (signb<0), preca, rnd_mode);
+ MPFR_EXP(a) = MPFR_EXP(b);
if (carry) {
an = (preca-1)/BITS_PER_MP_LIMB + 1;
sh = an * BITS_PER_MP_LIMB - preca;
@@ -47,7 +59,7 @@ mpfr_set4(a, b, rnd_mode, signb)
}
mpn_rshift(ap, ap, an, 1);
ap[an-1] |= (mp_limb_t) 1 << (BITS_PER_MP_LIMB-1);
- EXP(a)++;
+ MPFR_EXP(a)++;
}
- if (SIGN(a) != signb) CHANGE_SIGN(a);
+ if (MPFR_SIGN(a) * signb < 0) MPFR_CHANGE_SIGN(a);
}
diff --git a/mpfr/set_d.c b/mpfr/set_d.c
index 35c3ba21f..fe8006aae 100644
--- a/mpfr/set_d.c
+++ b/mpfr/set_d.c
@@ -1,7 +1,7 @@
/* mpfr_set_d, mpfr_get_d -- convert a multiple precision floating-point number
from/to a machine double precision float
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -20,17 +20,24 @@ along with the MPFR Library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
-#if __GNUC__ /* gcc "patched" headers seem to omit isnan... */
-extern int isnan(double);
-#endif
-#include <math.h> /* for isnan and NaN */
-
#include "gmp.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
#include "gmp-impl.h"
#include "longlong.h"
-#include "mpfr.h"
-#define NaN sqrt(-1) /* ensures a machine-independent NaN */
+#if (BITS_PER_MP_LIMB==32)
+#define MPFR_LIMBS_PER_DOUBLE 2
+#elif (BITS_PER_MP_LIMB==64)
+#define MPFR_LIMBS_PER_DOUBLE 1
+#endif
+
+int __mpfr_extract_double (mp_ptr, double, int);
+double __mpfr_scale2 (double, int);
+
+#define NaN (0./0.) /* ensures a machine-independent NaN */
+#define Infp (1/0.)
+#define Infm (-1/0.)
/* Included from gmp-2.0.2, patched to support denorms */
@@ -235,39 +242,56 @@ __mpfr_scale2 (d, exp)
void
#if __STDC__
-mpfr_set_d(mpfr_t r, double d, unsigned char rnd_mode)
+mpfr_set_d (mpfr_ptr r, double d, mp_rnd_t rnd_mode)
#else
-mpfr_set_d(r, d, rnd_mode)
- mpfr_t r;
+mpfr_set_d (r, d, rnd_mode)
+ mpfr_ptr r;
double d;
- unsigned char rnd_mode;
+ mp_rnd_t rnd_mode;
#endif
{
int signd, sizer; unsigned int cnt;
- if (d == 0) { SET_ZERO(r); return; }
- else if (isnan(d)) { SET_NAN(r); return; }
+ MPFR_CLEAR_FLAGS(r);
+ if (d == 0) {
+ union ieee_double_extract x;
+ MPFR_SET_ZERO(r);
+ /* set correct sign */
+ x.d = d;
+ if (((x.s.sig==1) && (MPFR_SIGN(r)>0))
+ || ((x.s.sig==0) && (MPFR_SIGN(r)<0)))
+ MPFR_CHANGE_SIGN(r);
+ return;
+ }
+ else if (DOUBLE_ISNAN(d)) { MPFR_SET_NAN(r); return; }
+ else if (DOUBLE_ISINF(d))
+ {
+ MPFR_SET_INF(r);
+ if ((d > 0 && (MPFR_SIGN(r) == -1)) || (d < 0 && (MPFR_SIGN(r) == 1)))
+ MPFR_CHANGE_SIGN(r);
+ return;
+ }
signd = (d < 0) ? -1 : 1;
d = ABS (d);
- sizer = (PREC(r)-1)/BITS_PER_MP_LIMB + 1;
+ sizer = (MPFR_PREC(r)-1)/BITS_PER_MP_LIMB + 1;
/* warning: __mpfr_extract_double requires at least two limbs */
if (sizer < MPFR_LIMBS_PER_DOUBLE)
- EXP(r) = __mpfr_extract_double (MANT(r), d, 0);
+ MPFR_EXP(r) = __mpfr_extract_double (MPFR_MANT(r), d, 0);
else
- EXP(r) = __mpfr_extract_double (MANT(r) + sizer - MPFR_LIMBS_PER_DOUBLE, d, 1);
+ MPFR_EXP(r) = __mpfr_extract_double (MPFR_MANT(r) + sizer - MPFR_LIMBS_PER_DOUBLE, d, 1);
if (sizer > MPFR_LIMBS_PER_DOUBLE)
- MPN_ZERO(MANT(r), sizer - MPFR_LIMBS_PER_DOUBLE);
+ MPN_ZERO(MPFR_MANT(r), sizer - MPFR_LIMBS_PER_DOUBLE);
- count_leading_zeros(cnt, MANT(r)[sizer-1]);
- if (cnt) mpn_lshift(MANT(r), MANT(r), sizer, cnt);
+ count_leading_zeros(cnt, MPFR_MANT(r)[sizer-1]);
+ if (cnt) mpn_lshift(MPFR_MANT(r), MPFR_MANT(r), sizer, cnt);
- EXP(r) -= cnt;
- if (SIZE(r)*signd<0) CHANGE_SIGN(r);
+ MPFR_EXP(r) -= cnt;
+ if (MPFR_SIGN(r)*signd<0) MPFR_CHANGE_SIGN(r);
- mpfr_round(r, rnd_mode, PREC(r));
+ mpfr_round(r, rnd_mode, MPFR_PREC(r));
return;
}
@@ -285,15 +309,21 @@ mpfr_get_d2(src, e)
mp_ptr qp;
int negative;
- if (FLAG_NAN(src)) {
+ if (MPFR_IS_NAN(src)) {
#ifdef DEBUG
printf("recognized NaN\n");
#endif
return NaN; }
- if (NOTZERO(src)==0) return 0.0;
- size = 1+(PREC(src)-1)/BITS_PER_MP_LIMB;
- qp = MANT(src);
- negative = (SIGN(src)==-1);
+ if (MPFR_IS_INF(src)) {
+#ifdef DEBUG
+ printf("Found Inf.\n");
+#endif
+ return (MPFR_SIGN(src) == 1 ? Infp : Infm);
+ }
+ if (MPFR_NOTZERO(src)==0) return 0.0;
+ size = 1+(MPFR_PREC(src)-1)/BITS_PER_MP_LIMB;
+ qp = MPFR_MANT(src);
+ negative = (MPFR_SIGN(src) < 0);
/* Warning: don't compute the abs(res) and set the sign afterwards,
otherwise the current machine rounding mode will not be taken
@@ -324,6 +354,6 @@ mpfr_get_d(src)
mpfr_srcptr src;
#endif
{
- return mpfr_get_d2(src, EXP(src));
+ return mpfr_get_d2(src, MPFR_EXP(src));
}
diff --git a/mpfr/set_dfl_prec.c b/mpfr/set_dfl_prec.c
index aa341be8a..f1ff78a08 100644
--- a/mpfr/set_dfl_prec.c
+++ b/mpfr/set_dfl_prec.c
@@ -1,6 +1,6 @@
/* mpfr_set_default_prec -- set the default precision
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -20,17 +20,18 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include "gmp.h"
+#include "mpfr.h"
#include "gmp-impl.h"
/* default is 53 bits */
-mp_size_t __gmp_default_fp_bit_precision = 53;
+mp_prec_t __gmp_default_fp_bit_precision = 53;
void
#if __STDC__
-mpfr_set_default_prec (unsigned long int prec_in_bits)
+mpfr_set_default_prec (mp_prec_t prec_in_bits)
#else
mpfr_set_default_prec (prec_in_bits)
- unsigned long int prec_in_bits;
+ mp_prec_t prec_in_bits;
#endif
{
__gmp_default_fp_bit_precision = prec_in_bits;
diff --git a/mpfr/set_f.c b/mpfr/set_f.c
index d3bb98dbf..bcdacbfad 100644
--- a/mpfr/set_f.c
+++ b/mpfr/set_f.c
@@ -1,6 +1,6 @@
/* mpfr_set_f -- set a MPFR number from a GNU MPF number
-Copyright (C) 1999-2000 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999-2000 Free Software Foundation.
This file is part of the MPFR Library.
@@ -24,31 +24,35 @@ MA 02111-1307, USA. */
#include "gmp-impl.h"
#include "longlong.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
void
#if __STDC__
-mpfr_set_f(mpfr_ptr y, mpf_srcptr x, char rnd_mode)
+mpfr_set_f(mpfr_ptr y, mpf_srcptr x, mp_rnd_t rnd_mode)
#else
mpfr_set_f(y, x, rnd_mode)
mpfr_ptr y;
mpf_srcptr x;
- char rnd_mode;
+ mp_rnd_t rnd_mode;
#endif
{
mp_limb_t *my, *mx, *tmp; unsigned long cnt, sx, sy;
TMP_DECL(marker);
- sx = ABS(SIZ(x)); sy = ABSSIZE(y);
- my = MANT(y); mx = MANT(x);
+ if (SIZ(x) * MPFR_SIGN(y) < 0) MPFR_CHANGE_SIGN(y);
+
+ MPFR_CLEAR_FLAGS(y);
+
+ TMP_MARK(marker);
+ sx = ABS(SIZ(x)); sy = MPFR_ABSSIZE(y);
+ my = MPFR_MANT(y); mx = PTR(x);
if (sx==0) { /* x is zero */
- SET_ZERO(y); return;
+ MPFR_SET_ZERO(y); return;
}
count_leading_zeros(cnt, mx[sx - 1]);
- if (SIZ(x)*SIGN(y)<0) CHANGE_SIGN(y);
-
if (sy < sx)
{
unsigned long xprec = sx * BITS_PER_MP_LIMB;
@@ -56,7 +60,7 @@ mpfr_set_f(y, x, rnd_mode)
tmp = (mp_limb_t*) TMP_ALLOC(xprec);
if (cnt) mpn_lshift(tmp, mx, sx, cnt);
else MPN_COPY(tmp, mx, sx);
- mpfr_round_raw(my, tmp, xprec, (SIZ(x)<0), PREC(y), rnd_mode);
+ mpfr_round_raw(my, tmp, xprec, (SIZ(x)<0), MPFR_PREC(y), rnd_mode);
}
else
{
@@ -66,7 +70,7 @@ mpfr_set_f(y, x, rnd_mode)
/* no rounding necessary, since y has a larger mantissa */
}
- EXP(y) = EXP(x) * BITS_PER_MP_LIMB - cnt;
+ MPFR_EXP(y) = EXP(x) * BITS_PER_MP_LIMB - cnt;
TMP_FREE(marker);
}
diff --git a/mpfr/set_prc_raw.c b/mpfr/set_prc_raw.c
new file mode 100644
index 000000000..b7a1633dd
--- /dev/null
+++ b/mpfr/set_prc_raw.c
@@ -0,0 +1,49 @@
+/* mpfr_set_prec_raw -- reset the precision of a floating-point number
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+void
+#if __STDC__
+mpfr_set_prec_raw (mpfr_ptr x, mp_prec_t p)
+#else
+mpfr_set_prec_raw (x, p)
+ mpfr_ptr x;
+ mp_prec_t p;
+#endif
+{
+ if (p==0) {
+ fprintf(stderr, "*** cannot set precision to 0 bits\n"); exit(1);
+ }
+
+ if (p > MPFR_ABSSIZE(x) * BITS_PER_MP_LIMB) {
+ fprintf(stderr, "*** precision too large for allocated space\n");
+ exit(1);
+ }
+
+ MPFR_PREC(x) = p;
+}
+
+
diff --git a/mpfr/set_prec.c b/mpfr/set_prec.c
index 418efe8eb..17adb5bb2 100644
--- a/mpfr/set_prec.c
+++ b/mpfr/set_prec.c
@@ -1,6 +1,6 @@
/* mpfr_set_prec -- reset the precision of a floating-point number
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -23,17 +23,18 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
void
#if __STDC__
-mpfr_set_prec (mpfr_t x, unsigned long int p)
+mpfr_set_prec (mpfr_ptr x, mp_prec_t p)
#else
mpfr_set_prec (x, p)
- mpfr_t x;
- unsigned long int p;
+ mpfr_ptr x;
+ mp_prec_t p;
#endif
{
- unsigned long xsize;
+ mp_prec_t xsize;
if (p==0) {
printf("*** cannot set precision to 0 bits\n"); exit(1);
@@ -41,22 +42,26 @@ mpfr_set_prec (x, p)
xsize = (p - 1)/BITS_PER_MP_LIMB + 1; /* new limb size */
- if (xsize > ABSSIZE(x)) {
- x -> _mp_d = (mp_ptr) (*__gmp_reallocate_func)
- (x -> _mp_d, ABSSIZE(x)*BYTES_PER_MP_LIMB, xsize * BYTES_PER_MP_LIMB);
- SIZE(x) = xsize; /* new number of allocated limbs */
+ if (xsize > MPFR_ABSSIZE(x)) {
+ MPFR_MANT(x) = (mp_ptr) (*_mp_reallocate_func) (MPFR_MANT(x),
+ MPFR_ABSSIZE(x)*BYTES_PER_MP_LIMB, xsize * BYTES_PER_MP_LIMB);
+ if (MPFR_MANT(x) == NULL) {
+ fprintf (stderr, "Error in mpfr_set_prec: no more memory available\n");
+ exit (1);
+ }
+ MPFR_SIZE(x) = xsize; /* new number of allocated limbs */
}
- x -> _mp_prec = p;
+ MPFR_PREC(x) = p;
}
-unsigned long int
+mp_prec_t
#if __STDC__
-mpfr_get_prec (mpfr_t x)
+mpfr_get_prec (mpfr_srcptr x)
#else
mpfr_get_prec (x)
- mpfr_t x;
+ mpfr_srcptr x;
#endif
{
- return x -> _mp_prec;
+ return MPFR_PREC(x);
}
diff --git a/mpfr/set_q.c b/mpfr/set_q.c
new file mode 100644
index 000000000..c6c364d6e
--- /dev/null
+++ b/mpfr/set_q.c
@@ -0,0 +1,64 @@
+/* mpfr_set_q -- set a floating-point number from a multiple-precision rational
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+/* set f to the rational q */
+void
+#if __STDC__
+mpfr_set_q (mpfr_ptr f, mpq_srcptr q, mp_rnd_t rnd)
+#else
+mpfr_set_q (f, q, rnd)
+ mpfr_ptr f;
+ mpq_srcptr q;
+ mp_rnd_t rnd;
+#endif
+{
+ int sign;
+ mpz_srcptr num, den;
+ unsigned int prec;
+ mpfr_t n,d;
+
+ MPFR_CLEAR_FLAGS(f);
+ num = mpq_numref(q);
+ sign = mpz_cmp_ui(num, 0);
+ if (sign==0) {
+ MPFR_SET_ZERO(f);
+ return;
+ }
+
+ den = mpq_denref(q);
+ prec = MPFR_PREC(f);
+ mpfr_init2(n, mpz_sizeinbase(num, 2));
+ mpfr_set_z(n, num, GMP_RNDZ); /* result is exact */
+ mpfr_init2(d, mpz_sizeinbase(den, 2));
+ mpfr_set_z(d, den, GMP_RNDZ); /* result is exact */
+ MPFR_PREC(f) = prec;
+ mpfr_div(f, n, d, rnd);
+ mpfr_clear(n); mpfr_clear(d);
+}
+
+
+
diff --git a/mpfr/set_rnd.c b/mpfr/set_rnd.c
new file mode 100644
index 000000000..34e728b8e
--- /dev/null
+++ b/mpfr/set_rnd.c
@@ -0,0 +1,38 @@
+/* mpfr_set_default_rounding_mode -- set the default rounding mode
+
+Copyright (C) 1999 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "mpfr.h"
+#include "gmp-impl.h"
+
+mp_rnd_t __gmp_default_rounding_mode = 0;
+
+void
+#if __STDC__
+mpfr_set_default_rounding_mode (mp_rnd_t rnd_mode)
+#else
+mpfr_set_default_rounding_mode (rnd_mode)
+ mp_rnd_t rnd_mode;
+#endif
+{
+ __gmp_default_rounding_mode = rnd_mode;
+}
+
diff --git a/mpfr/set_si.c b/mpfr/set_si.c
index b2d916cd1..9594682fe 100644
--- a/mpfr/set_si.c
+++ b/mpfr/set_si.c
@@ -1,6 +1,6 @@
/* mpfr_set_si, mpfr_set_ui -- set a MPFR number from a machine integer
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -24,57 +24,86 @@ MA 02111-1307, USA. */
#include "gmp-impl.h"
#include "longlong.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
void
#if __STDC__
-mpfr_set_si(mpfr_ptr x, long i, unsigned char rnd_mode)
+mpfr_set_si (mpfr_ptr x, long int i, mp_rnd_t rnd_mode)
#else
-mpfr_set_si(x, i, rnd_mode)
+mpfr_set_si (x, i, rnd_mode)
mpfr_ptr x;
- long i;
- unsigned char rnd_mode;
+ long int i;
+ mp_rnd_t rnd_mode;
#endif
{
- unsigned long xn, cnt; mp_limb_t ai;
+ unsigned long xn, cnt; mp_limb_t ai, *xp;
- if (i==0) { SET_ZERO(x); return; }
- xn = (PREC(x)-1)/BITS_PER_MP_LIMB;
+ MPFR_CLEAR_FLAGS(x);
+ if (i==0) { MPFR_SET_ZERO(x); return; }
+ xn = (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB;
ai = ABS(i);
count_leading_zeros(cnt, ai);
- x -> _mp_d[xn] = ai << cnt;
+ xp = MPFR_MANT(x);
+ xp[xn] = ai << cnt;
/* don't forget to put zero in lower limbs */
- MPN_ZERO(MANT(x), xn);
- x -> _mp_exp = BITS_PER_MP_LIMB - cnt;
+ MPN_ZERO(xp, xn);
+
+ MPFR_EXP(x) = BITS_PER_MP_LIMB - cnt;
+
+ /* round if MPFR_PREC(x) smaller than length of i */
+ if (MPFR_PREC(x) < BITS_PER_MP_LIMB-cnt) {
+ cnt = mpfr_round_raw(xp+xn, xp+xn, BITS_PER_MP_LIMB-cnt, (ai<0), MPFR_PREC(x),
+ rnd_mode);
+ if (cnt) { /* special case 1.000...000 */
+ MPFR_EXP(x)++;
+ xp[xn] = ((mp_limb_t) 1) << (BITS_PER_MP_LIMB-1);
+ }
+ }
+
/* warning: don't change the precision of x! */
- if (i*SIGN(x) < 0) CHANGE_SIGN(x);
+ if (i*MPFR_SIGN(x) < 0) MPFR_CHANGE_SIGN(x);
return;
}
void
#if __STDC__
-mpfr_set_ui(mpfr_ptr x, unsigned long i, unsigned char rnd_mode)
+mpfr_set_ui (mpfr_ptr x, unsigned long int i, mp_rnd_t rnd_mode)
#else
-mpfr_set_ui(x, i, rnd_mode)
+mpfr_set_ui (x, i, rnd_mode)
mpfr_ptr x;
- long i;
- unsigned char rnd_mode;
+ unsigned long int i;
+ mp_rnd_t rnd_mode;
#endif
{
- unsigned int xn, cnt;
+ unsigned int xn, cnt; mp_limb_t *xp;
- if (i==0) { SET_ZERO(x); return; }
- xn = (PREC(x)-1)/BITS_PER_MP_LIMB;
+ MPFR_CLEAR_FLAGS(x);
+ if (i==0) { MPFR_SET_ZERO(x); return; }
+ xn = (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB;
count_leading_zeros(cnt, (mp_limb_t) i);
- x -> _mp_d[xn] = ((mp_limb_t) i) << cnt;
+ xp = MPFR_MANT(x);
+ xp[xn] = ((mp_limb_t) i) << cnt;
/* don't forget to put zero in lower limbs */
- MPN_ZERO(MANT(x), xn);
- x -> _mp_exp = BITS_PER_MP_LIMB - cnt;
+ MPN_ZERO(xp, xn);
+
+ MPFR_EXP(x) = BITS_PER_MP_LIMB - cnt;
+
+ /* round if MPFR_PREC(x) smaller than length of i */
+ if (MPFR_PREC(x) < BITS_PER_MP_LIMB-cnt) {
+ cnt = mpfr_round_raw(xp+xn, xp+xn, BITS_PER_MP_LIMB-cnt, 0, MPFR_PREC(x),
+ rnd_mode);
+ if (cnt) { /* special case 1.000...000 */
+ MPFR_EXP(x)++;
+ xp[xn] = ((mp_limb_t) 1) << (BITS_PER_MP_LIMB-1);
+ }
+ }
+
/* warning: don't change the precision of x! */
- if (SIGN(x) < 0) CHANGE_SIGN(x);
+ if (MPFR_SIGN(x) < 0) MPFR_CHANGE_SIGN(x);
return;
}
diff --git a/mpfr/set_str.c b/mpfr/set_str.c
new file mode 100644
index 000000000..0c0b029cf
--- /dev/null
+++ b/mpfr/set_str.c
@@ -0,0 +1,155 @@
+/* mpfr_set_str -- set a floating-point number from a string
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAS_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+int
+#if __STDC__
+mpfr_set_str(mpfr_ptr x, char *str, int base, mp_rnd_t rnd_mode)
+#else
+mpfr_set_str(x, str, base, rnd_mode)
+ mpfr_ptr x;
+ char *str;
+ int base;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ char negative = 0, *endptr;
+ unsigned long k = 0, l, q;
+ long expn = 0, e;
+ mpz_t mantissa;
+ mpfr_t y, z;
+
+ mpz_init(mantissa); mpz_set_ui(mantissa, 0);
+ l = strlen(str);
+ if (*str == '-') { negative = 1; str++; l--; }
+ else if (*str == '+') { str++; l--; }
+
+ while (*str == '0') { str++; l--; } /* skip initial zeros */
+
+ /* allowed characters are '0' to '0'+base-1 if base <= 10,
+ and '0' to '9' plus 'a' to 'a'+base-11 if 10 < base <= 36 */
+ while ((isdigit((unsigned char) *str) && (unsigned char) *str < '0'+base)
+ || (islower((unsigned char) *str) && (unsigned char) *str < 'a'+base-10))
+ {
+ mpz_mul_ui(mantissa, mantissa, base);
+ mpz_add_ui(mantissa, mantissa, isdigit((unsigned char) *str) ?
+ (*str)-'0' : (*str)-'a'+10);
+ str++; l--;
+ }
+
+ /* k is the number of non-zero digits before the decimal point */
+
+ if (*str == '.')
+ {
+ str++; l--;
+ while ((isdigit((unsigned char) *str) && (unsigned char) *str < '0'+base)
+ || (islower((unsigned char) *str) && (unsigned char) *str < 'a'+base-10))
+ {
+ mpz_mul_ui(mantissa, mantissa, base);
+ mpz_add_ui(mantissa, mantissa, isdigit((unsigned char) *str) ?
+ (*str)-'0' : (*str)-'a'+10);
+ str++; l--;
+ k++;
+ }
+ }
+
+ if ((base <= 10 && (*str == 'e' || *str == 'E')) || *str == '@')
+ {
+ str++; l--;
+ e = strtol(str, &endptr, 10); /* signed exponent after 'e', 'E' or '@' */
+ expn = e - k;
+ if (expn > e)
+ fprintf(stderr, "Warning: exponent underflow in mpfr_set_str\n");
+ }
+ else if (l) {
+ fprintf(stderr, "Unexpected end of string in mpfr_set_str: %s\n", str);
+ return -1;
+ }
+ else {
+ expn = -k;
+ endptr = str;
+ }
+
+ /* the number is mantissa*base^expn */
+
+ q = (MPFR_PREC(x)/BITS_PER_MP_LIMB)*BITS_PER_MP_LIMB;
+ mpfr_init(y);
+ mpfr_init(z);
+
+ do {
+ q += BITS_PER_MP_LIMB;
+ mpfr_set_prec(y, q);
+ mpfr_set_z(y, mantissa, GMP_RNDN); /* error <= 1/2*ulp(y) */
+
+ mpfr_set_prec(z, q);
+ if (expn>0) {
+ e = mpfr_ui_pow_ui(z, base, expn, GMP_RNDN);
+ mpfr_mul(y, y, z, GMP_RNDN);
+ }
+ else if (expn<0) {
+ e = mpfr_ui_pow_ui(z, base, -expn, GMP_RNDN);
+ mpfr_div(y, y, z, GMP_RNDN);
+ }
+ else e=1;
+ if (negative) mpfr_neg(y, y, GMP_RNDN);
+
+ /* now y is an approximation of mantissa*base^expn with error at most
+ 2^e*ulp(y) */
+
+ } while (mpfr_can_round(y, q-e, GMP_RNDN, rnd_mode, MPFR_PREC(x))==0
+ && q<=2*MPFR_PREC(x));
+
+ mpfr_set(x, y, rnd_mode);
+
+ mpz_clear(mantissa);
+ mpfr_clear(y);
+ mpfr_clear(z);
+ return ((*endptr=='\0') ? 0 : -1);
+}
+
+int
+#if __STDC__
+mpfr_init_set_str(mpfr_ptr x, char *str, int base, mp_rnd_t rnd_mode)
+#else
+mpfr_init_set_str(x, str, base, rnd_mode)
+ mpfr_ptr x;
+ char *str;
+ int base;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ mpfr_init(x);
+ return mpfr_set_str(x, str, base, rnd_mode);
+}
+
diff --git a/mpfr/set_str_raw.c b/mpfr/set_str_raw.c
index d0945c4bc..e00645cef 100644
--- a/mpfr/set_str_raw.c
+++ b/mpfr/set_str_raw.c
@@ -1,6 +1,6 @@
/* mpfr_set_str_raw -- set a floating-point number from a binary string
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -30,6 +30,7 @@ MA 02111-1307, USA. */
#include "gmp-impl.h"
#include "longlong.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
/* Currently the number should be of the form +/- xxxx.xxxxxxEyy, with
decimal exponent. The mantissa of x is supposed to be large enough
@@ -37,24 +38,45 @@ MA 02111-1307, USA. */
void
#if __STDC__
-mpfr_set_str_raw(mpfr_ptr x, char *str)
+mpfr_set_str_raw (mpfr_ptr x, char *str)
#else
-mpfr_set_str_raw(x, str)
+mpfr_set_str_raw (x, str)
mpfr_ptr x;
char *str;
#endif
{
char *str2, *str0, negative = 0;
- unsigned long j, l, k = 0, xsize, cnt; mp_limb_t *xp;
+ unsigned long j, l, k = 0, xsize, cnt, alloc; mp_limb_t *xp;
long expn = 0, e; char *endstr2;
- xp = x -> _mp_d;
- xsize = 1 + (PREC(x)-1)/BITS_PER_MP_LIMB;
- str0 = str2 = (char *) malloc((strlen(str)+1)*sizeof(char));
+ xp = MPFR_MANT(x);
+ xsize = 1 + (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB;
+ alloc = (strlen(str)+1) * sizeof(char);
+ str0 = str2 = (char *) (*_mp_allocate_func) (alloc);
+
+ if (str0 == NULL) {
+ fprintf (stderr, "Error in mpfr_set_str_raw: no more memory available\n");
+ exit (1);
+ }
if (*str == '-') { negative = 1; str++; }
else if (*str == '+') str++;
+
+ if (*str == 'I')
+ {
+ MPFR_SET_INF(x);
+ if (MPFR_ISNEG(x) != negative) MPFR_CHANGE_SIGN(x);
+ return;
+ }
+
+ if (*str == 'N')
+ {
+ MPFR_SET_NAN(x);
+ return;
+ }
+ MPFR_CLEAR_FLAGS(x);
+
while (*str == '0') { str++; }
while (*str == '0' || *str == '1')
@@ -82,7 +104,11 @@ mpfr_set_str_raw(x, str)
endstr2 = str2;
*str2 = (char) 0; /* end of string */
- l = (strlen(str0) - 1) / BITS_PER_MP_LIMB + 1; str2 = str0;
+ l = (strlen(str0) - 1) / BITS_PER_MP_LIMB + 1; str2 = str0;
+ if (l > xsize) {
+ fprintf (stderr, "Error: mantissa larger than precision of destination variable in mpfr_set_str_raw\n");
+ exit (1);
+ }
/* str2[0]..endstr2[-1] contains the mantissa */
for (k = 1; k <= l; k++)
@@ -102,10 +128,10 @@ mpfr_set_str_raw(x, str)
count_leading_zeros(cnt, xp[xsize - 1]);
if (cnt) mpn_lshift(xp, xp, xsize, cnt);
- x -> _mp_exp = expn - cnt;
- x -> _mp_size = xsize; if (negative) CHANGE_SIGN(x);
+ MPFR_EXP(x) = expn - cnt;
+ MPFR_SIZE(x) = xsize; if (negative) MPFR_CHANGE_SIGN(x);
- free(str0);
+ (*_mp_free_func) (str0, alloc);
/* May change to take into account : syntax errors, overflow in exponent,
string truncated because of size of x */
diff --git a/mpfr/set_z.c b/mpfr/set_z.c
index de9132033..0815ca324 100644
--- a/mpfr/set_z.c
+++ b/mpfr/set_z.c
@@ -1,6 +1,6 @@
/* mpfr_set_z -- set a floating-point number from a multiple-precision integer
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -20,39 +20,47 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
#include "gmp.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
#include "gmp-impl.h"
#include "longlong.h"
-#include "mpfr.h"
/* set f to the integer z */
int
#if __STDC__
-mpfr_set_z (mpfr_ptr f, mpz_srcptr z, unsigned char rnd)
+mpfr_set_z (mpfr_ptr f, mpz_srcptr z, mp_rnd_t rnd)
#else
mpfr_set_z (f, z, rnd)
- mpfr_ptr f;
- mpz_srcptr z;
- unsigned char rnd;
+ mpfr_ptr f;
+ mpz_srcptr z;
+ mp_rnd_t rnd;
#endif
{
- int fn, zn, k, dif, sign_z, sh; mp_limb_t *fp = MANT(f), *zp, cc, c2;
+ int fn, zn, k, dif, sign_z, sh; mp_limb_t *fp = MPFR_MANT(f), *zp, cc, c2;
+
+ MPFR_CLEAR_FLAGS (f); /* z cannot be NaN nor Inf */
+
+ sign_z = mpz_cmp_ui (z, 0);
+
+ if (sign_z==0) {
+ MPFR_SET_ZERO(f);
+ return 0;
+ }
- sign_z = mpz_cmp_ui(z,0);
- if (sign_z==0) return (SIZE(f)=0);
- fn = 1 + (PREC(f)-1)/BITS_PER_MP_LIMB;
+ fn = 1 + (MPFR_PREC(f)-1)/BITS_PER_MP_LIMB;
zn = ABS(SIZ(z));
dif = zn-fn;
zp = PTR(z);
count_leading_zeros(k, zp[zn-1]);
- EXP(f) = zn*BITS_PER_MP_LIMB-k;
- if (SIGN(f)*sign_z<0) CHANGE_SIGN(f);
+ MPFR_EXP(f) = zn*BITS_PER_MP_LIMB-k;
+ if (MPFR_SIGN(f)*sign_z<0) MPFR_CHANGE_SIGN(f);
if (dif>=0) { /* number has to be truncated */
if (k) {
mpn_lshift(fp, zp + dif, fn, k);
if (dif) *fp += zp[dif-1] >> (BITS_PER_MP_LIMB-k);
}
else MPN_COPY(fp, zp + dif, fn);
- sh = fn*BITS_PER_MP_LIMB-PREC(f);
+ sh = fn*BITS_PER_MP_LIMB-MPFR_PREC(f);
cc = *fp & (((mp_limb_t)1 << sh) - 1);
*fp = *fp & ~cc;
if (rnd==GMP_RNDN) {
diff --git a/mpfr/sin_cos.c b/mpfr/sin_cos.c
new file mode 100644
index 000000000..21f746b70
--- /dev/null
+++ b/mpfr/sin_cos.c
@@ -0,0 +1,246 @@
+/* mpfr_sin_cos -- sine and cosine of a floating-point number
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+int mpfr_sin_aux (mpfr_ptr, mpz_srcptr, int, int);
+int mpfr_cos_aux (mpfr_ptr, mpz_srcptr, int, int);
+
+#undef A
+#undef B
+#define C
+#define C1 3
+#define C2 2
+#define GENERIC mpfr_sin_aux
+#include "generic.c"
+#undef C
+#undef C1
+#undef C2
+#undef GENERIC
+
+#undef A
+#undef B
+#define C
+#define C1 1
+#define C2 2
+#define GENERIC mpfr_cos_aux
+#include "generic.c"
+
+#define shift (BITS_PER_MP_LIMB / 2)
+
+int
+#if __STDC__
+mpfr_sin_cos (mpfr_ptr sinus, mpfr_ptr cosinus, mpfr_srcptr x, mp_rnd_t rnd_mode)
+#else
+mpfr_sin_cos (sinus, cosinus, x, rnd_mode)
+ mpfr_ptr sinus;
+ mpfr_ptr cosinus;
+ mpfr_srcptr x;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ mpfr_t t_sin, t_cos;
+ mpfr_t x_copy;
+ int i,k;
+ mpz_t uk;
+ mpz_t square;
+ mpfr_t tmp_sin, tmp_cos;
+ mpfr_t tmp;
+ mpfr_t inter;
+ int ttt;
+ int twopoweri;
+ int Prec;
+ int loop;
+ int prec_x;
+ int shift_x = 0;
+ int good = 0;
+ int realprec = 0, target_prec;
+ int iter;
+ int factor;
+ int logn;
+ int tmp_factor;
+ int tmpi;
+
+ if (sinus == cosinus) {
+ fprintf (stderr, "Error in mpfr_sin_cos: 1st and 2nd operands must be different\n");
+ exit (1);
+ }
+
+ if (MPFR_IS_NAN(x) || MPFR_IS_INF(x)) {
+ MPFR_SET_NAN(sinus);
+ MPFR_SET_NAN(cosinus);
+ return 1; /* inexact */
+ }
+
+ if (!MPFR_NOTZERO(x)) {
+ mpfr_set_ui(sinus, 0, GMP_RNDN);
+ mpfr_set_ui(cosinus, 1, GMP_RNDN);
+ return 0; /* exact results */
+ }
+
+ prec_x = _mpfr_ceil_log2 ((double) MPFR_PREC(x) / BITS_PER_MP_LIMB);
+ ttt = MPFR_EXP(x);
+ mpfr_init2(x_copy, MPFR_PREC(x));
+ mpfr_set(x_copy,x,GMP_RNDD);
+ mpz_init(square);
+ /* on fait le shift pour que le nombre soit inferieur a 1 */
+ if (ttt > 0)
+ {
+ shift_x = ttt;
+ mpfr_mul_2exp(x_copy,x,-ttt, GMP_RNDN);
+ ttt = MPFR_EXP(x_copy);
+ }
+ target_prec = MPFR_PREC(sinus);
+ if (MPFR_PREC(cosinus) > target_prec) target_prec = MPFR_PREC(cosinus);
+ logn = _mpfr_ceil_log2 ((double) target_prec);
+ if (logn < 2) logn = 2;
+ factor = logn;
+ realprec = target_prec + logn;
+ mpz_init (uk);
+ while (!good) {
+ Prec = realprec + 2*shift + 2 + shift_x + factor;
+ k = _mpfr_ceil_log2 ((double) Prec / BITS_PER_MP_LIMB);
+
+ /* now we extract */
+ mpfr_init2(t_sin, Prec);
+ mpfr_init2(t_cos, Prec);
+ mpfr_init2(tmp, Prec);
+ mpfr_init2(tmp_sin, Prec);
+ mpfr_init2(tmp_cos, Prec);
+ mpfr_init2(inter, Prec);
+ mpfr_set_ui(tmp_sin,0,GMP_RNDN);
+ mpfr_set_ui(tmp_cos,1,GMP_RNDN);
+ twopoweri = BITS_PER_MP_LIMB;
+ if (k <= prec_x) iter = k; else iter= prec_x;
+ for(i = 0; i <= iter; i++){
+ mpfr_extract (uk, x_copy, i);
+ if (i)
+ {
+ mpz_mul (square, uk, uk);
+ mpz_neg (square, square);
+ mpfr_sin_aux (t_sin, square, 2*(twopoweri - ttt) + 2, k - i + 1);
+ mpfr_cos_aux (t_cos, square, 2*(twopoweri - ttt) + 2, k - i + 1);
+ mpfr_set_z (tmp, uk, GMP_RNDD);
+ mpfr_mul (t_sin, t_sin, tmp, GMP_RNDD);
+ mpfr_div_2exp (t_sin, t_sin, twopoweri - ttt, GMP_RNDD);
+ }
+ else
+ {
+ /* cas particulier : on est oblige de faire les calculs avec x/2^.
+ puis elever au carre (plus rapide) */
+ mpz_set (square, uk);
+ mpz_mul(square, square, square);
+ mpz_neg(square, square);
+ /* pour l'instant, shift = 0 ... */
+ /* ATTENTION, IL FAUT AUSSI MULTIPLIER LE DENOMINATEUR */
+ mpfr_sin_aux(t_sin,square, 2*(shift + twopoweri - ttt) + 2, k+1);
+ mpfr_cos_aux(t_cos,square, 2*(shift + twopoweri - ttt) + 2, k+1);
+ mpfr_set_z (tmp, uk, GMP_RNDD);
+ mpfr_mul(t_sin, t_sin, tmp,GMP_RNDD);
+ /* LA AUSSI, IL FAUT PENSER A DECALER DE twopoweri - ttt) */
+ mpfr_div_2exp(t_sin,t_sin, twopoweri - ttt + shift, GMP_RNDD);
+ for (loop= 0 ; loop < shift; loop++){
+ /* t_sin = sin(a)
+ t_cos = cos(a) */
+ /* on veut t_sin = 2 sin a cos a
+ et t_cos = 2 * cos^2 - 1 */
+ mpfr_mul(t_sin, t_sin, t_cos, GMP_RNDD);
+ mpfr_mul_2exp(t_sin, t_sin, 1, GMP_RNDD);
+
+ mpfr_mul(t_cos, t_cos, t_cos, GMP_RNDD);
+ mpfr_mul_2exp(t_cos, t_cos, 1, GMP_RNDD);
+ mpfr_sub_ui(t_cos, t_cos, 1, GMP_RNDD);
+ }
+ }
+ /* on utilise cos(a+b) = cos a cos b - sin a sin b
+ sin(a+b) = sin a cos b + cos a sin b */
+ /* Donnees :
+ tmp = cos(a)
+ tmp_sin = sin(a)
+ t_sin = sin(b)
+ t_cos = cos(b) */
+ mpfr_set(tmp, tmp_cos,GMP_RNDD);
+ /* inter = sin a sin b */
+ mpfr_mul(inter, tmp_sin, t_sin, GMP_RNDD);
+ /* tmp_cos = cos a cos b */
+ mpfr_mul(tmp_cos, tmp_cos, t_cos, GMP_RNDD);
+ /* tmp_cos = cos (a+b) */
+ mpfr_sub(tmp_cos, tmp_cos, inter, GMP_RNDD);
+ /* inter = cos a sin b */
+ mpfr_mul(inter, tmp, t_sin, GMP_RNDD);
+ /* tmp_sin = sin a cos b */
+ mpfr_mul(tmp_sin, tmp_sin, t_cos, GMP_RNDD);
+ /* tmp_sin = sin (a+b) */
+ mpfr_add(tmp_sin, tmp_sin, inter, GMP_RNDD);
+ twopoweri <<= 1;
+ }
+ tmp_factor= factor;
+ for (loop= 0 ; loop < shift_x; loop++){
+ mpfr_mul(tmp_sin, tmp_sin, tmp_cos, GMP_RNDD);
+ mpfr_mul_2exp(tmp_sin, tmp_sin, 1, GMP_RNDD);
+ mpfr_mul(tmp_cos, tmp_cos, tmp_cos, GMP_RNDD);
+ mpfr_mul_2exp(tmp_cos, tmp_cos, 1, GMP_RNDD);
+ tmpi = -MPFR_EXP(tmp_cos);
+ mpfr_set_ui(tmp, 1, GMP_RNDN);
+ mpfr_sub(tmp_cos, tmp_cos, tmp, GMP_RNDD);
+ /* rep\'erer si le nombre de chiffres obtenu est suffisant pour
+ avoir la bonne pr\'ecision. Le probl\`eme : comment faire ?
+ la pr\'ecision s'obtient en comparant
+ (Prec-factor) a la pr\'ecision obtenue r\'eellement, celle-ci
+ \'etant donn\'ee par Prec + MPFR_EXP(tmp_cos).
+ il faut donc comparer MPFR_EXP(tmp_cos) a factor */
+ tmp_factor -= -MPFR_EXP(tmp_cos) + tmpi;
+ if (tmp_factor <= 0)
+ {
+ factor += -tmp_factor + 5;
+ goto try_again;
+ }
+ }
+ if (mpfr_can_round(tmp_sin, realprec, GMP_RNDD, rnd_mode, MPFR_PREC(sinus)) &&
+ mpfr_can_round(tmp_cos, realprec, GMP_RNDD, rnd_mode, MPFR_PREC(cosinus))) {
+ mpfr_set(sinus, tmp_sin, rnd_mode);
+ mpfr_set(cosinus, tmp_cos, rnd_mode);
+ good = 1;
+ }
+ else {
+ realprec += 3*logn;
+ }
+ try_again:
+ mpfr_clear(t_sin);
+ mpfr_clear(t_cos);
+ mpfr_clear(tmp);
+ mpfr_clear(tmp_sin);
+ mpfr_clear(tmp_cos);
+ mpfr_clear(inter);
+ }
+ mpz_clear (uk);
+ mpz_clear (square);
+ mpfr_clear (x_copy);
+ return 1; /* inexact result */
+}
+
+
+
diff --git a/mpfr/sqrt.c b/mpfr/sqrt.c
index a34ff6dae..19d0f14b1 100644
--- a/mpfr/sqrt.c
+++ b/mpfr/sqrt.c
@@ -1,6 +1,6 @@
/* mpfr_sqrt -- square root of a floating-point number
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -19,18 +19,24 @@ along with the MPFR Library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
-#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
-#include "longlong.h"
+#include "mpfr-impl.h"
/* #define DEBUG */
int
-mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, unsigned char rnd_mode)
+#if __STDC__
+mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, mp_rnd_t rnd_mode)
+#else
+mpfr_sqrt (r, u, rnd_mode)
+ mpfr_ptr r;
+ mpfr_srcptr u;
+ mp_rnd_t rnd_mode;
+#endif
{
mp_ptr up, rp, tmp, remp;
mp_size_t usize, rrsize;
@@ -38,23 +44,52 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, unsigned char rnd_mode)
mp_size_t prec, err;
mp_limb_t q_limb;
long rw, nw, k;
- int exact = 0;
+ int exact = 0, t;
unsigned long cc = 0;
char can_round = 0;
TMP_DECL (marker); TMP_DECL(marker0);
- if (FLAG_NAN(u) || SIGN(u) == -1) { SET_NAN(r); return 0; }
-
- prec = PREC(r);
+ if (MPFR_IS_NAN(u)) {
+ MPFR_SET_NAN(r);
+ return 1;
+ }
+
+ if (MPFR_SIGN(u) < 0) {
+ if (MPFR_IS_INF(u) || MPFR_NOTZERO(u)) {
+ MPFR_SET_NAN(r);
+ return 1;
+ }
+ else { /* sqrt(-0) = -0 */
+ MPFR_SET_ZERO(r);
+ if (MPFR_SIGN(r) > 0) MPFR_CHANGE_SIGN(r);
+ return 0;
+ }
+ }
- if (!NOTZERO(u))
+ MPFR_CLEAR_NAN(r);
+
+ if (MPFR_SIGN(r) < 0) MPFR_CHANGE_SIGN(r);
+ if (MPFR_IS_INF(u))
+ {
+ MPFR_SET_INF(r);
+ return 1;
+ }
+
+ MPFR_CLEAR_INF(r);
+
+ prec = MPFR_PREC(r);
+
+ if (!MPFR_NOTZERO(u))
{
- EXP(r) = 0;
- MPN_ZERO(MANT(r), ABSSIZE(r));
- return 1;
+ MPFR_EXP(r) = 0;
+ rsize = (prec-1)/BITS_PER_MP_LIMB + 1;
+ MPN_ZERO(MPFR_MANT(r), rsize);
+ return 0;
}
- up = MANT(u);
+ up = MPFR_MANT(u);
+
+ usize = (MPFR_PREC(u) - 1)/BITS_PER_MP_LIMB + 1;
#ifdef DEBUG
printf("Entering square root : ");
@@ -64,9 +99,8 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, unsigned char rnd_mode)
/* Compare the mantissas */
- usize = (PREC(u) - 1)/BITS_PER_MP_LIMB + 1;
- rsize = ((PREC(r) + 2 + (EXP(u) & 1))/BITS_PER_MP_LIMB + 1) << 1;
- rrsize = (PREC(r) + 2 + (EXP(u) & 1))/BITS_PER_MP_LIMB + 1;
+ rsize = ((MPFR_PREC(r) + 2 + (MPFR_EXP(u) & 1))/BITS_PER_MP_LIMB + 1) << 1;
+ rrsize = (MPFR_PREC(r) + 2 + (MPFR_EXP(u) & 1))/BITS_PER_MP_LIMB + 1;
/* One extra bit is needed in order to get the square root with enough
precision ; take one extra bit for rrsize in order to solve more
easily the problem of rounding to nearest.
@@ -76,24 +110,24 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, unsigned char rnd_mode)
*/
TMP_MARK(marker0);
- if (EXP(u) & 1) /* Shift u one bit to the right */
+ if (MPFR_EXP(u) & 1) /* Shift u one bit to the right */
{
- if (PREC(u) & (BITS_PER_MP_LIMB - 1))
+ if (MPFR_PREC(u) & (BITS_PER_MP_LIMB - 1))
{
up = TMP_ALLOC(usize*BYTES_PER_MP_LIMB);
- mpn_rshift(up, u->_mp_d, usize, 1);
+ mpn_rshift(up, MPFR_MANT(u), usize, 1);
}
else
{
up = TMP_ALLOC((usize + 1)*BYTES_PER_MP_LIMB);
- if (mpn_rshift(up + 1, u->_mp_d, ABSSIZE(u), 1))
+ if (mpn_rshift(up + 1, MPFR_MANT(u), usize, 1))
up [0] = ((mp_limb_t) 1) << (BITS_PER_MP_LIMB - 1);
else up[0] = 0;
usize++;
}
}
- EXP(r) = ((EXP(u) + (EXP(u) & 1)) / 2) ;
+ MPFR_EXP(r) = ((MPFR_EXP(u) + (MPFR_EXP(u) & 1)) / 2) ;
do
{
@@ -121,11 +155,11 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, unsigned char rnd_mode)
#ifdef DEBUG
printf("Taking the sqrt of : ");
for(k = rsize - 1; k >= 0; k--) {
- printf("+%lu*2^%lu",tmp[k],k*mp_bits_per_limb); }
+ printf("+%lu*2^%lu",tmp[k],k*BITS_PER_MP_LIMB); }
printf(".\n");
#endif
- q_limb = kara_sqrtrem (rp, remp, tmp, rsize);
+ q_limb = mpn_sqrtrem_new (rp, remp, tmp, rsize);
#ifdef DEBUG
printf("The result is : \n");
@@ -135,7 +169,7 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, unsigned char rnd_mode)
#endif
can_round = (mpfr_can_round_raw(rp, rrsize, 1, err,
- GMP_RNDZ, rnd_mode, PREC(r)));
+ GMP_RNDZ, rnd_mode, MPFR_PREC(r)));
/* If we used all the limbs of both the dividend and the divisor,
then we have the correct RNDZ rounding */
@@ -167,8 +201,8 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, unsigned char rnd_mode)
if (can_round)
{
- cc = mpfr_round_raw(rp, rp, err, 0, PREC(r), rnd_mode);
- rrsize = (PREC(r) - 1)/BITS_PER_MP_LIMB + 1;
+ cc = mpfr_round_raw(rp, rp, err, 0, MPFR_PREC(r), rnd_mode);
+ rrsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1;
}
else
/* Use the return value of sqrtrem to decide of the rounding */
@@ -184,7 +218,7 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, unsigned char rnd_mode)
case GMP_RNDN :
/* Not in the situation ...0 111111 */
- rw = (PREC(r) + 1) & (BITS_PER_MP_LIMB - 1);
+ rw = (MPFR_PREC(r) + 1) & (BITS_PER_MP_LIMB - 1);
if (rw) { rw = BITS_PER_MP_LIMB - rw; nw = 0; } else nw = 1;
if ((rp[nw] >> rw) & 1 && /* Not 0111111111 */
(q_limb || /* Nonzero remainder */
@@ -195,26 +229,33 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, unsigned char rnd_mode)
case GMP_RNDU :
if (q_limb)
- cc = mpn_add_1(rp, rp, rrsize, 1 << (BITS_PER_MP_LIMB -
- (PREC(r) &
- (BITS_PER_MP_LIMB - 1))));
+ {
+ t = MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1);
+ if (t)
+ {
+ cc = mpn_add_1(rp, rp, rrsize, 1 << (BITS_PER_MP_LIMB - t));
+ }
+ else
+ cc = mpn_add_1 (rp, rp, rrsize, 1);
+ }
}
if (cc) {
mpn_rshift(rp, rp, rrsize, 1);
rp[rrsize-1] |= (mp_limb_t) 1 << (BITS_PER_MP_LIMB-1);
- r->_mp_exp++;
+ MPFR_EXP(r)++;
}
fin:
rsize = rrsize;
- rrsize = (PREC(r) - 1)/BITS_PER_MP_LIMB + 1;
- MPN_COPY(r->_mp_d, rp + rsize - rrsize, rrsize);
+ rrsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1;
+ MPN_COPY(MPFR_MANT(r), rp + rsize - rrsize, rrsize);
- if (PREC(r) & (BITS_PER_MP_LIMB - 1))
- MANT(r) [0] &= ~(((mp_limb_t)1 << (BITS_PER_MP_LIMB -
- (PREC(r) & (BITS_PER_MP_LIMB - 1)))) - 1) ;
+ if (MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1))
+ MPFR_MANT(r) [0] &= ~(((mp_limb_t)1 << (BITS_PER_MP_LIMB -
+ (MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1)))) - 1) ;
- TMP_FREE(marker0); TMP_FREE (marker);
- return exact;
+ TMP_FREE (marker);
+ TMP_FREE(marker0);
+ return exact;
}
diff --git a/mpfr/sqrt_ui.c b/mpfr/sqrt_ui.c
new file mode 100644
index 000000000..3453e3d0f
--- /dev/null
+++ b/mpfr/sqrt_ui.c
@@ -0,0 +1,58 @@
+/* mpfr_sqrt_ui -- square root of a machine integer
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+int
+#if __STDC__
+mpfr_sqrt_ui (mpfr_ptr r, unsigned long u, mp_rnd_t rnd_mode)
+#else
+mpfr_sqrt_ui (r, u, rnd_mode)
+ mpfr_ptr r;
+ unsigned long u;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ int error = 0;
+ mpfr_t uu;
+ mp_limb_t up[1];
+ unsigned long cnt;
+
+ if (u) { /* if u=0, do nothing */
+ MPFR_INIT1(up, uu, BITS_PER_MP_LIMB, 1);
+ count_leading_zeros(cnt, (mp_limb_t) u);
+ *up = (mp_limb_t) u << cnt;
+ MPFR_EXP(uu) = BITS_PER_MP_LIMB-cnt;
+
+ error = mpfr_sqrt(r, uu, rnd_mode);
+ }
+ else {
+ MPFR_CLEAR_FLAGS(r);
+ MPFR_SET_ZERO(r);
+ }
+ return error;
+}
diff --git a/mpfr/sqrtrem.c b/mpfr/sqrtrem.c
new file mode 100644
index 000000000..740d56997
--- /dev/null
+++ b/mpfr/sqrtrem.c
@@ -0,0 +1,225 @@
+/* mpn_sqrtrem_new -- integer square root with remainder
+ (should be directly integrated in a future release of GNU MP)
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h> /* for NULL */
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+
+mp_size_t mpn_sqrtrem1 (mp_ptr, mp_ptr, mp_srcptr);
+mp_limb_t mpn_sqrtrem2 (mp_ptr, mp_ptr, mp_srcptr);
+mp_limb_t mpn_dq_sqrtrem (mp_ptr, mp_ptr, mp_size_t);
+mp_size_t mpn_sqrtrem_new (mp_ptr, mp_ptr, mp_srcptr, mp_size_t);
+
+/* table generated by isqrt(2^8*i) $ i=64..255 in MuPAD */
+static const unsigned char approx_tab[192] = {
+128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153,
+ 154, 155, 155, 156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164,
+ 165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175,
+ 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 183, 184, 185,
+ 185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 193, 194,
+ 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 203, 203,
+ 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, 212,
+ 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220,
+ 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228,
+ 229, 229, 230, 230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236,
+ 236, 237, 237, 238, 238, 239, 240, 240, 241, 241, 242, 242, 243, 243,
+ 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250,
+ 251, 251, 252, 252, 253, 253, 254, 254, 255};
+
+/* same as mpn_sqrtrem, but for size=1 and {np, 1} normalized */
+mp_size_t mpn_sqrtrem1 (mp_ptr sp, mp_ptr rp, mp_srcptr np)
+{
+ mp_limb_t np0, s, r, q, u;
+ int prec;
+
+ /* first compute a 8-bit approximation from the high 8-bits of np[0] */
+ np0 = np[0];
+ q = np0 >> (BITS_PER_MP_LIMB - 8);
+ /* 2^6 = 64 <= q < 256 = 2^8 */
+ s = approx_tab[q - 64]; /* 128 <= s < 255 */
+ r = (np0 >> (BITS_PER_MP_LIMB - 16)) - s * s; /* r <= 2*s */
+ if (r > 2 * s) { r -= 2 * s + 1; s++; }
+#ifdef DEBUG
+ if (r > 2*s) {
+ fprintf(stderr, "Error: r > 2*s, np[0]=%lu r=%lu s=%lu\n", np[0], r, s); exit(1);
+ }
+#endif
+
+ prec = 8;
+ np0 <<= 2 * prec;
+ while (2*prec < BITS_PER_MP_LIMB) {
+ /* invariant: s has prec bits, and r <= 2*s */
+ r = (r << prec) + (np0 >> (BITS_PER_MP_LIMB - prec));
+ np0 <<= prec;
+ u = 2 * s;
+ q = r / u;
+ u = r - q * u;
+ s = (s << prec) + q;
+ u = (u << prec) + (np0 >> (BITS_PER_MP_LIMB - prec));
+ q = q * q;
+ r = u - q;
+ if (u < q) {
+ r += 2 * s - 1;
+ s --;
+ }
+ np0 <<= prec;
+ prec = 2 * prec;
+ }
+ sp[0] = s;
+ if (rp != NULL) rp[0] = r;
+ return (r) ? 1 : 0;
+}
+
+#define Prec (BITS_PER_MP_LIMB >> 1)
+
+/* same as mpn_sqrtrem, but for size=2 and {np, 2} normalized
+ return cc such that {np, 2} = sp[0]^2 + cc*2^BITS+PER_MP_LIMB + rp[0] */
+mp_limb_t mpn_sqrtrem2 (mp_ptr sp, mp_ptr rp, mp_srcptr np)
+{
+ mp_limb_t qhl, q, u, np0;
+ int cc;
+
+ np0 = np[0];
+ mpn_sqrtrem1(sp, rp, np+1);
+ qhl = 0;
+ while (rp[0] >= sp[0]) {
+ qhl ++;
+ rp[0] -= sp[0];
+ }
+ /* now rp[0] < sp[0] < 2^Prec */
+ rp[0] = (rp[0] << Prec) + (np0 >> Prec);
+ u = 2 * sp[0];
+ q = rp[0] / u;
+ u = rp[0] - q * u;
+ q += (qhl & 1) << (Prec-1);
+ qhl >>= 1; /* if qhl=1, necessary q=0 as qhl*2^Prec + q <= 2^Prec */
+ /* now we have (initial rp[0])<<Prec + np0>>Prec = (qhl<<Prec + q) * (2sp[0]) + u */
+ sp[0] = ((sp[0]+qhl) << Prec) + q;
+ cc = u >> Prec;
+ rp[0] = (u << Prec) + (np0 & (((mp_limb_t)1 << Prec) - 1));
+ /* subtract q * q or qhl*2^(2*Prec) from rp */
+ cc -= mpn_sub_1(rp, rp, 1, q * q) + qhl;
+ /* now subtract 2*q*2^Prec + 2^(2*Prec) if qhl is set */
+ if (cc < 0) {
+ cc += (sp[0]) ? mpn_add_1(rp, rp, 1, sp[0]) : 1;
+ cc += mpn_add_1(rp, rp, 1, --sp[0]);
+ }
+ return cc;
+}
+
+/* writes in {sp, n} the square root (rounded towards zero) of {np, 2n},
+ and in {np, n} the low n limbs of the remainder, returns the high
+ limb of the remainder (which is 0 or 1).
+ Assumes {np, 2n} is normalized, i.e. np[2n-1] >= B/4
+ where B=2^BITS_PER_MP_LIMB.
+*/
+mp_limb_t mpn_dq_sqrtrem (mp_ptr sp, mp_ptr np, mp_size_t n)
+{
+ mp_limb_t q; /* carry out of {sp, n} */
+ int c, b; /* carry out of remainder */
+ mp_size_t l, h;
+
+ if (n == 1) return mpn_sqrtrem2 (sp, np, np);
+
+ l = n / 2;
+ h = n - l;
+ q = mpn_dq_sqrtrem (sp + l, np + 2 * l, h);
+ if (q) mpn_sub_n (np + 2 * l, np + 2 * l, sp + l, h);
+ q += mpn_divrem (sp, 0, np + l, n, sp + l, h);
+ c = sp[0] & 1;
+ mpn_rshift (sp, sp, l, 1);
+ sp[l-1] |= q << (BITS_PER_MP_LIMB - 1);
+ q >>= 1;
+ if (c) c = mpn_add_n (np + l, np + l, sp + l, h);
+ mpn_mul_n (np + n, sp, sp, l);
+ b = q + mpn_sub_n (np, np, np + n, 2 * l);
+ c -= (l == h) ? b : mpn_sub_1 (np + 2 * l, np + 2 * l, 1, b);
+ q = mpn_add_1 (sp + l, sp + l, h, q);
+
+ if (c < 0) {
+ c += mpn_addmul_1 (np, sp, n, 2) + 2 * q;
+ c -= mpn_sub_1 (np, np, n, 1);
+ q -= mpn_sub_1 (sp, sp, n, 1);
+ }
+
+ return c;
+}
+
+/* main function */
+mp_size_t mpn_sqrtrem_new (mp_ptr sp, mp_ptr rp, mp_srcptr np, mp_size_t nn)
+{
+ mp_limb_t *tp, s0[1], cc;
+ int c, tn;
+ mp_size_t rn;
+ TMP_DECL (marker);
+
+#ifdef DEBUG
+ if (np[nn-1] == 0) {
+ fprintf (stderr, "Error in mpn_sqrtrem: most significant limb is zero\n");
+ exit(1);
+ }
+#endif
+
+ count_leading_zeros(c, np[nn-1]);
+
+ if (nn == 1 && c == 0) return mpn_sqrtrem1 (sp, rp, np);
+
+ c = c / 2; /* we have to shift left by 2c bits to normalize {np, nn} */
+ tn = (nn+1) / 2; /* 2*tn is the smallest even integer >= nn */
+
+ TMP_MARK (marker);
+ if ((nn % 2) || (c > 0)) {
+ tp = (mp_limb_t*) TMP_ALLOC (2 * tn * BYTES_PER_MP_LIMB);
+ tp[0] = 0; /* needed only when 2*tn > nn, but saves a test */
+ if (c) mpn_lshift(tp + 2*tn - nn, np, nn, 2 * c);
+ else MPN_COPY (tp + 2*tn - nn, np, nn);
+ rn = mpn_dq_sqrtrem (sp, tp, tn);
+ /* we have 2^(2k)*N = S^2 + R where k = c + (2tn-nn)*BITS_PER_MP_LIMB/2,
+ thus 2^(2k)*N = (S-s0)^2 + 2*S*s0 - s0^2 + R where s0=S mod 2^k */
+ c += (nn % 2) * BITS_PER_MP_LIMB / 2; /* c now represents k */
+ s0[0] = sp[0] & (((mp_limb_t) 1 << c) - 1); /* S mod 2^k */
+ rn += mpn_addmul_1 (tp, sp, tn, 2 * s0[0]); /* R = R + 2*s0*S */
+ cc = mpn_submul_1 (tp, s0, 1, s0[0]);
+ rn -= (tn > 1) ? mpn_sub_1(tp + 1, tp + 1, tn - 1, cc) : cc;
+ mpn_rshift (sp, sp, tn, c);
+ tp[tn] = rn;
+ if (rp == NULL) rp = tp;
+ c = c << 1;
+ if (c < BITS_PER_MP_LIMB) tn++; else { tp++; c -= BITS_PER_MP_LIMB; }
+ if (c) mpn_rshift (rp, tp, tn, c);
+ else MPN_COPY(rp, tp, tn);
+ rn = tn;
+ }
+ else {
+ if (rp == NULL)
+ rp = (mp_limb_t*) TMP_ALLOC (nn * BYTES_PER_MP_LIMB);
+ if (rp != np) MPN_COPY (rp, np, nn);
+ rn = tn + (rp[tn] = mpn_dq_sqrtrem (sp, rp, tn));
+ }
+ while (rn && rp[rn-1]==0) rn--;
+ TMP_FREE (marker);
+
+ return rn;
+}
+
diff --git a/mpfr/sub.c b/mpfr/sub.c
index dfe755b73..4971472de 100644
--- a/mpfr/sub.c
+++ b/mpfr/sub.c
@@ -1,6 +1,6 @@
/* mpfr_sub -- subtract two floating-point numbers
-Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+Copyright (C) 1999 Free Software Foundation.
This file is part of the MPFR Library.
@@ -23,24 +23,31 @@ MA 02111-1307, USA. */
#include "gmp.h"
#include "gmp-impl.h"
#include "mpfr.h"
+#include "mpfr-impl.h"
/* #define DEBUG */
+#define ONE ((mp_limb_t) 1)
+
extern void mpfr_add1 _PROTO((mpfr_ptr, mpfr_srcptr, mpfr_srcptr,
- unsigned char, int));
+ mp_rnd_t, int));
+mp_limb_t mpn_sub_lshift_n (mp_limb_t *, mp_limb_t *, int, int, int);
+void mpfr_sub1 (mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t, int);
/* put in ap[0]..ap[an-1] the value of bp[0]..bp[n-1] shifted by sh bits
- to the left minus ap[0]..ap[n-1], with 0 <= sh < mp_bits_per_limb, and
+ to the left minus ap[0]..ap[n-1], with 0 <= sh < BITS_PER_MP_LIMB, and
returns the borrow.
*/
mp_limb_t
#if __STDC__
mpn_sub_lshift_n (mp_limb_t *ap, mp_limb_t *bp, int n, int sh, int an)
#else
-mpn_sub_lshift_n (ap, bp, n, sh, an) mp_limb_t *ap, *bp; int n,sh,an;
+mpn_sub_lshift_n (ap, bp, n, sh, an)
+ mp_limb_t *ap, *bp;
+ int n,sh,an;
#endif
{
- mp_limb_t c, bh;
+ mp_limb_t c, bh=0;
/* shift b to the left */
if (sh) bh = mpn_lshift(bp, bp, n, sh);
@@ -48,7 +55,7 @@ mpn_sub_lshift_n (ap, bp, n, sh, an) mp_limb_t *ap, *bp; int n,sh,an;
/* shift back b to the right */
if (sh) {
mpn_rshift(bp, bp, n, sh);
- bp[n-1] += bh<<(mp_bits_per_limb-sh);
+ bp[n-1] += bh<<(BITS_PER_MP_LIMB-sh);
}
return c;
}
@@ -56,155 +63,189 @@ mpn_sub_lshift_n (ap, bp, n, sh, an) mp_limb_t *ap, *bp; int n,sh,an;
/* signs of b and c differ, abs(b)>=abs(c), diff_exp>=0 */
void
#if __STDC__
-mpfr_sub1(mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, unsigned char rnd_mode, int diff_exp)
+mpfr_sub1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c,
+ mp_rnd_t rnd_mode, int diff_exp)
#else
-mpfr_sub1(a, b, c, rnd_mode, diff_exp)
+mpfr_sub1 (a, b, c, rnd_mode, diff_exp)
mpfr_ptr a;
mpfr_srcptr b;
- mpfr_srcptr c;
- unsigned char rnd_mode;
+ mpfr_srcptr c;
+ mp_rnd_t rnd_mode;
int diff_exp;
#endif
{
- mp_limb_t *ap, *bp, *cp, cc, c2; unsigned int an,bn,cn;
+ mp_limb_t *ap, *bp, *cp, cc, c2; unsigned int an, bn, cn;
int sh,dif,k,cancel,cancel1,cancel2;
TMP_DECL(marker);
#ifdef DEBUG
- printf("b= "); if (SIGN(b)>=0) putchar(' ');
+ printf("b= "); if (MPFR_SIGN(b)>=0) putchar(' ');
mpfr_print_raw(b); putchar('\n');
- printf("c= "); if (SIGN(c)>=0) putchar(' ');
+ printf("c= "); if (MPFR_SIGN(c)>=0) putchar(' ');
for (k=0;k<diff_exp;k++) putchar(' '); mpfr_print_raw(c);
putchar('\n');
printf("b=%1.20e c=%1.20e\n",mpfr_get_d(b),mpfr_get_d(c));
#endif
cancel = mpfr_cmp2(b, c);
- /* we have to take into account the first (PREC(a)+cancel) bits from b */
- cancel1 = cancel/mp_bits_per_limb; cancel2 = cancel%mp_bits_per_limb;
+ /* we have to take into account the first (MPFR_PREC(a)+cancel) bits from b */
+ cancel1 = cancel/BITS_PER_MP_LIMB; cancel2 = cancel%BITS_PER_MP_LIMB;
TMP_MARK(marker);
- ap = MANT(a);
- bp = MANT(b);
- cp = MANT(c);
+ ap = MPFR_MANT(a);
+ bp = MPFR_MANT(b);
+ cp = MPFR_MANT(c);
if (ap == bp) {
- bp = (mp_ptr) TMP_ALLOC(ABSSIZE(b) * BYTES_PER_MP_LIMB);
- MPN_COPY (bp, ap, ABSSIZE(b));
+ bp = (mp_ptr) TMP_ALLOC(MPFR_ABSSIZE(b) * BYTES_PER_MP_LIMB);
+ MPN_COPY (bp, ap, MPFR_ABSSIZE(b));
if (ap == cp) { cp = bp; }
}
else if (ap == cp)
{
- cp = (mp_ptr) TMP_ALLOC (ABSSIZE(c) * BYTES_PER_MP_LIMB);
- MPN_COPY(cp, ap, ABSSIZE(c));
+ cp = (mp_ptr) TMP_ALLOC (MPFR_ABSSIZE(c) * BYTES_PER_MP_LIMB);
+ MPN_COPY(cp, ap, MPFR_ABSSIZE(c));
}
- an = (PREC(a)-1)/mp_bits_per_limb+1; /* number of significant limbs of a */
- sh = an*mp_bits_per_limb-PREC(a); /* non-significant bits in low limb */
- bn = (PREC(b)-1)/mp_bits_per_limb+1; /* number of significant limbs of b */
- cn = (PREC(c)-1)/mp_bits_per_limb + 1;
- EXP(a) = EXP(b)-cancel;
+ an = (MPFR_PREC(a)-1)/BITS_PER_MP_LIMB+1; /* number of significant limbs of a */
+ sh = an*BITS_PER_MP_LIMB-MPFR_PREC(a); /* non-significant bits in low limb */
+ bn = (MPFR_PREC(b)-1)/BITS_PER_MP_LIMB+1; /* number of significant limbs of b */
+ cn = (MPFR_PREC(c)-1)/BITS_PER_MP_LIMB + 1;
+ MPFR_EXP(a) = MPFR_EXP(b)-cancel;
/* adjust sign to that of b */
- if (SIGN(a)*SIGN(b)<0) CHANGE_SIGN(a);
+ if (MPFR_SIGN(a)*MPFR_SIGN(b)<0) MPFR_CHANGE_SIGN(a);
/* case 1: diff_exp>=prec(a), i.e. c only affects the last bit
through rounding */
- dif = PREC(a)-diff_exp;
+ dif = MPFR_PREC(a)-diff_exp;
#ifdef DEBUG
- printf("PREC(a)=%d an=%u PREC(b)=%d bn=%u PREC(c)=%d diff_exp=%u dif=%d cancel=%d\n",
- PREC(a),an,PREC(b),bn,PREC(c),diff_exp,dif,cancel);
+ printf("MPFR_PREC(a)=%d an=%u MPFR_PREC(b)=%d bn=%u MPFR_PREC(c)=%d diff_exp=%u dif=%d cancel=%d\n",
+ MPFR_PREC(a),an,MPFR_PREC(b),bn,MPFR_PREC(c),diff_exp,dif,cancel);
#endif
- if (dif<=0) { /* diff_exp>=PREC(a): c does not overlap with a */
- /* either PREC(b)<=PREC(a), and we can copy the mantissa of b directly
- into that of a, or PREC(b)>PREC(a) and we have to round b-c */
- if (PREC(b)<=PREC(a)+cancel) {
+ if (dif<=0) { /* diff_exp>=MPFR_PREC(a): c does not overlap with a */
+ /* either MPFR_PREC(b)<=MPFR_PREC(a), and we can copy the mantissa of b directly
+ into that of a, or MPFR_PREC(b)>MPFR_PREC(a) and we have to round b-c */
+ if (MPFR_PREC(b)<=MPFR_PREC(a)+cancel) {
if (cancel2) mpn_lshift(ap+(an-bn+cancel1), bp, bn-cancel1, cancel2);
else MPN_COPY(ap+(an-bn+cancel1), bp, bn-cancel1);
/* fill low significant limbs with zero */
MPN_ZERO(ap, an-bn+cancel1);
/* now take c into account */
if (rnd_mode==GMP_RNDN) { /* to nearest */
- /* if diff_exp > PREC(a), no change */
- if (diff_exp==PREC(a)) {
+ /* if diff_exp > MPFR_PREC(a), no change */
+ if (diff_exp==MPFR_PREC(a)) {
/* if c is not zero, then as it is normalized, we have to subtract
one to the lsb of a if c>1/2, or c=1/2 and lsb(a)=1 (round to
even) */
- if (NOTZERO(c)) { /* c is not zero */
+ if (MPFR_NOTZERO(c)) { /* c is not zero */
/* check whether mant(c)=1/2 or not */
- cc = *cp - ((mp_limb_t)1<<(mp_bits_per_limb-1));
+ cc = *cp - (ONE<<(BITS_PER_MP_LIMB-1));
if (cc==0) {
- bp = cp+(PREC(c)-1)/mp_bits_per_limb;
+ bp = cp+(MPFR_PREC(c)-1)/BITS_PER_MP_LIMB;
while (cp<bp && cc==0) cc = *++cp;
}
- if (cc || (ap[an-1] & (mp_limb_t)1<<sh)) goto sub_one_ulp;
+ if (cc || (ap[an-1] & ONE<<sh)) goto sub_one_ulp;
/* mant(c) > 1/2 or mant(c) = 1/2: subtract 1 iff lsb(a)=1 */
}
}
else if (ap[an-1]==0) { /* case b=2^n */
- ap[an-1] = (mp_limb_t) 1 << (BITS_PER_MP_LIMB-1);
- EXP(a)++;
+ ap[an-1] = ONE << (BITS_PER_MP_LIMB-1);
+ MPFR_EXP(a)++;
}
}
- else if ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
- (ISNEG(b) && rnd_mode==GMP_RNDD)) {
+ else if ((MPFR_ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
+ (MPFR_ISNEG(b) && rnd_mode==GMP_RNDD)) {
/* round up: nothing to do */
if (ap[an-1]==0) { /* case b=2^n */
- ap[an-1] = (mp_limb_t) 1 << (BITS_PER_MP_LIMB-1);
- EXP(a)++;
+ ap[an-1] = ONE << (BITS_PER_MP_LIMB-1);
+ MPFR_EXP(a)++;
}
}
else {
/* round down: subtract 1 ulp iff c<>0 */
- if (NOTZERO(c)) goto sub_one_ulp;
+ if (MPFR_NOTZERO(c)) goto sub_one_ulp;
}
}
- else { /* PREC(b)>PREC(a) : we have to round b-c */
+ else { /* MPFR_PREC(b)>MPFR_PREC(a) : we have to round b-c */
k=bn-an;
/* first copy the 'an' most significant limbs of b to a */
MPN_COPY(ap, bp+k, an);
- if (rnd_mode==GMP_RNDN) { /* to nearest */
- /* first check whether the truncated bits from b are 1/2*lsb(a) */
+ { /* treat all rounding modes together */
+ mp_limb_t c2old; int sign=0; long int cout=0;
+
if (sh) {
- cc = *ap & (((mp_limb_t)1<<sh)-1);
+ cc = *ap & ((ONE<<sh)-1);
*ap &= ~cc; /* truncate last bits */
- cc -= (mp_limb_t)1<<(sh-1);
}
- else /* no bit to truncate */
- cc = bp[--k] - ((mp_limb_t)1<<(mp_bits_per_limb-1));
- if ((long)cc>0) { /* suppose sizeof(long)=sizeof(mp_limb_t) */
- goto add_one_ulp; /* trunc(b)>1/2*lsb(a) -> round up */
+ else cc=0;
+
+ dif += sh;
+ if (dif>0) { /* c overlaps by dif bits with that last unused sh bits
+ from least significant limb of b */
+ cn--;
+ c2old = cp[cn]; /* last limb from c considered */
+ cout -= mpn_sub_1(&cc, &cc, 1, c2old >> (BITS_PER_MP_LIMB-dif));
}
- else if (cc==0) {
- while (k>1 && cc==0) cc=bp[--k];
- /* now if the truncated part of b = 1/2*lsb(a), check whether c=0 */
- if (NOTZERO(c) || (*ap & ((mp_limb_t)1<<sh))) goto sub_one_ulp;
- /* if trunc(b)-c is exactly 1/2*lsb(a) : round to even lsb */
+ else c2old = 0;
+
+ /* trailing bits from b - c are -cout*2^BITS_PER_MP_LIMB + cc,
+ last considered limb of c is c2old, remains to take into account
+ its BITS_PER_MP_LIMB-dif low bits */
+
+ if (sh && rnd_mode==GMP_RNDN) {
+ if (cout>=0) {
+ sign = 1;
+ cout -= mpn_sub_1(&cc, &cc, 1, ONE<<(sh-1));
+ }
+ else {
+ sign = -1;
+ cout += mpn_add_1(&cc, &cc, 1, ONE<<(sh-1));
+ }
}
- /* if cc<0 : trunc(b) < 1/2*lsb(a) -> round down, i.e. do nothing */
- }
- else { /* round towards infinity or zero */
- if (sh) {
- cc = *ap & (((mp_limb_t)1<<sh)-1);
- *ap &= ~cc; /* truncate last bits */
+
+ if (cout==0) { /* if cout<0, it will remain negative */
+ if (dif<0) dif += BITS_PER_MP_LIMB;
+ while (cout==0 && (k || cn)) {
+ cout = cc;
+ cc = (k) ? bp[--k] : 0;
+ if (sh==0) {
+ if (cout>=0) {
+ sign = 1;
+ cout -= mpn_sub_1(&cc, &cc, 1, ONE << (BITS_PER_MP_LIMB-1));
+ }
+ else {
+ sign = -1;
+ cout += mpn_add_1(&cc, &cc, 1, ONE << (BITS_PER_MP_LIMB-1));
+ }
+ sh = 0;
+ }
+ /* next limb from c to consider is cp[cn-1], with lower part of
+ c2old */
+ c2 = c2old << dif;
+ if (cn && (dif>=0)) {
+ cn--;
+ c2old = cp[cn];
+ c2 += c2old >> (BITS_PER_MP_LIMB-dif);
+ }
+ else dif += BITS_PER_MP_LIMB;
+ cout -= mpn_sub_1(&cc, &cc, 1, c2);
+ }
}
- else cc=0;
- cn--;
- c2 = (dif>-sh) ? cp[cn]>>(mp_bits_per_limb-dif-sh) : 0;
- while (cc==c2 && (k || cn)) {
- if (k) cc = bp[--k];
- if (cn) {
- c2 = cp[cn]<<(dif+sh);
- if (--cn) c2 += cp[cn]>>(mp_bits_per_limb-dif-sh);
- }
+ if (cout==0) cout=(cc!=0);
+ if (rnd_mode==GMP_RNDU) sign=1;
+ else if (rnd_mode==GMP_RNDD || rnd_mode==GMP_RNDZ) sign=-1;
+ /* even rounding rule: */
+ if (rnd_mode==GMP_RNDN) {
+ if (cout==0 && (*ap & (ONE<<sh))) cout=sign;
}
- dif = ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
- (ISNEG(b) && rnd_mode==GMP_RNDD));
- /* round towards infinity if dif=1, towards zero otherwise */
- if (dif && cc>c2) goto add_one_ulp;
- else if (dif==0 && cc<c2) goto sub_one_ulp;
+ else /* rounding does not depend from sign of b for GMP_RNDN */
+ if (MPFR_ISNEG(b)) sign=-sign;
+ /* round towards infinity if sign=1, towards zero otherwise */
+ if ((sign==1) && cout>0) goto add_one_ulp;
+ else if ((sign==-1) && cout<0) goto sub_one_ulp;
}
}
}
- else { /* case 2: diff_exp < PREC(a) : c overlaps with a by dif bits */
+ else { /* case 2: diff_exp < MPFR_PREC(a) : c overlaps with a by dif bits */
/* first copy upper part of c into a (after shift) */
int overlap;
dif += cancel;
- k = (dif-1)/mp_bits_per_limb + 1; /* only the highest k limbs from c
+ k = (dif-1)/BITS_PER_MP_LIMB + 1; /* only the highest k limbs from c
have to be considered */
if (k<an) {
MPN_ZERO(ap+k, an-k); /* do it now otherwise ap[k] may be
@@ -213,48 +254,53 @@ mpfr_sub1(a, b, c, rnd_mode, diff_exp)
#ifdef DEBUG
printf("cancel=%d dif=%d k=%d cn=%d sh=%d\n",cancel,dif,k,cn,sh);
#endif
- if (dif<=PREC(c)) { /* c has to be truncated */
- dif = dif % mp_bits_per_limb;
- dif = (dif) ? mp_bits_per_limb-dif-sh : -sh;
+ if (dif<=MPFR_PREC(c)) { /* c has to be truncated */
+ dif = dif % BITS_PER_MP_LIMB;
+ dif = (dif) ? BITS_PER_MP_LIMB-dif-sh : -sh;
/* we have to shift by dif bits to the right */
if (dif>0) {
mpn_rshift(ap, cp+(cn-k), (k<=an) ? k : an, dif);
- if (k>an) ap[an-1] += cp[cn-k+an]<<(mp_bits_per_limb-dif);
+ if (k>an) ap[an-1] += cp[cn-k+an]<<(BITS_PER_MP_LIMB-dif);
}
else if (dif<0) {
- cc = mpn_lshift(ap, cp+(cn-k), k, -dif);
+ cc = mpn_lshift(ap, cp+(cn-k), (k<=an) ? k : an, -dif);
if (k<an) ap[k]=cc;
/* put the non-significant bits in low limb for further rounding */
if (cn >= k+1)
- ap[0] += cp[cn-k-1]>>(mp_bits_per_limb+dif);
+ ap[0] += cp[cn-k-1]>>(BITS_PER_MP_LIMB+dif);
}
- else MPN_COPY(ap, cp+(cn-k), k);
+ else MPN_COPY(ap, cp+(cn-k), (k<=an) ? k : an);
overlap=1;
}
else { /* c is not truncated, but we have to fill low limbs with 0 */
- MPN_ZERO(ap, k-cn);
+ MPN_ZERO(ap, (k-cn<an) ? k-cn : an);
overlap = cancel-diff_exp;
#ifdef DEBUG
printf("0:a="); mpfr_print_raw(a); putchar('\n');
printf("overlap=%d\n",overlap);
#endif
if (overlap>=0) {
- cn -= overlap/mp_bits_per_limb;
- overlap %= mp_bits_per_limb;
+ if (overlap/BITS_PER_MP_LIMB <= cn)
+ cn -= overlap/BITS_PER_MP_LIMB;
+ else cn=0;
+ overlap %= BITS_PER_MP_LIMB;
/* warning: a shift of zero with mpn_lshift is not allowed */
if (overlap) {
if (an<cn) {
mpn_lshift(ap, cp+(cn-an), an, overlap);
- ap[0] += cp[cn-an-1]>>(mp_bits_per_limb-overlap);
+ ap[0] += cp[cn-an-1]>>(BITS_PER_MP_LIMB-overlap);
+ }
+ else {
+ /* warning: mpn_lshift doesn't seem to like cn=0 */
+ if (cn) mpn_lshift(ap+(an-cn), cp, cn, overlap);
}
- else mpn_lshift(ap+(an-cn), cp, cn, overlap);
}
else MPN_COPY(ap+(an-cn), cp, cn);
}
else { /* shift to the right by -overlap bits */
overlap = -overlap;
- k = overlap/mp_bits_per_limb;
- overlap = overlap % mp_bits_per_limb;
+ k = overlap/BITS_PER_MP_LIMB;
+ overlap = overlap % BITS_PER_MP_LIMB;
if (overlap) cc = mpn_rshift(ap+(an-k-cn), cp, cn, overlap);
else {
MPN_COPY(ap+(an-k-cn), cp, cn);
@@ -270,16 +316,18 @@ mpfr_sub1(a, b, c, rnd_mode, diff_exp)
/* here overlap=1 iff ulp(c)<ulp(a) */
/* then put high limbs to zero */
/* now add 'an' upper limbs of b in place */
- if (PREC(b)<=PREC(a)+cancel) { int i, imax;
+ if (MPFR_PREC(b)<=MPFR_PREC(a)+cancel) { int i, imax;
overlap += 2;
/* invert low limbs */
- imax = (int)an-(int)bn+cancel1;
+ imax = (int)an - (int)bn + cancel1;
+ if (imax > (int)an) imax = an;
for (i=0;i<imax;i++) ap[i] = ~ap[i];
cc = (i) ? mpn_add_1(ap, ap, i, 1) : 1;
- mpn_sub_lshift_n(ap+i, bp, bn-cancel1, cancel2, an);
- mpn_sub_1(ap+i, ap+i, an-i, (mp_limb_t)1-cc);
+ if (cancel1 < bn) mpn_sub_lshift_n(ap+i, bp, bn-cancel1, cancel2, an);
+ /* warning: mpn_sub_1 doesn't accept a zero length */
+ if (i < an) mpn_sub_1(ap+i, ap+i, an-i, ONE-cc);
}
- else /* PREC(b) > PREC(a): we have to truncate b */
+ else /* MPFR_PREC(b) > MPFR_PREC(a): we have to truncate b */
mpn_sub_lshift_n(ap, bp+(bn-an-cancel1), an, cancel2, an);
/* remains to do the rounding */
#ifdef DEBUG
@@ -289,40 +337,63 @@ mpfr_sub1(a, b, c, rnd_mode, diff_exp)
if (rnd_mode==GMP_RNDN) { /* to nearest */
int kc;
/* four cases: overlap =
- (0) PREC(b) > PREC(a) and diff_exp+PREC(c) <= PREC(a)
- (1) PREC(b) > PREC(a) and diff_exp+PREC(c) > PREC(a)
- (2) PREC(b) <= PREC(a) and diff_exp+PREC(c) <= PREC(a)
- (3) PREC(b) <= PREC(a) and diff_exp+PREC(c) > PREC(a) */
+ (0) MPFR_PREC(b) > MPFR_PREC(a) and diff_exp+MPFR_PREC(c) <= MPFR_PREC(a)
+ (1) MPFR_PREC(b) > MPFR_PREC(a) and diff_exp+MPFR_PREC(c) > MPFR_PREC(a)
+ (2) MPFR_PREC(b) <= MPFR_PREC(a) and diff_exp+MPFR_PREC(c) <= MPFR_PREC(a)
+ (3) MPFR_PREC(b) <= MPFR_PREC(a) and diff_exp+MPFR_PREC(c) > MPFR_PREC(a) */
switch (overlap)
{
case 1: /* both b and c to round */
kc = cn-k; /* remains kc limbs from c */
k = bn-an; /* remains k limbs from b */
/* truncate last bits and store the difference with 1/2*ulp in cc */
- cc = *ap & (((mp_limb_t)1<<sh)-1);
- *ap &= ~cc; /* truncate last bits */
- cc -= (mp_limb_t)1<<(sh-1);
- while ((cc==0 || cc==-1) && k!=0 && kc!=0) {
- kc--;
- cc -= mpn_sub_1(&c2, bp+(--k), 1, (cp[kc]>>dif) +
- (cp[kc+1]<<(mp_bits_per_limb-dif)));
- if (cc==0 || cc==-1) cc=c2;
+ c2 = *ap & ((ONE<<sh)-1);
+ *ap &= ~c2; /* truncate last bits */
+ cc = -mpn_sub_1(&c2, &c2, 1, ONE<<(sh-1));
+ if (cc==0) cc=c2;
+ /* loop invariant: cc*2^BITS_PER_MP_LIMB+c2 is the current difference
+ between b - 1/2*ulp(a) and c shifted by dif bits to the right.
+ cc > 0 ==> add one ulp
+ cc < 0 ==> truncate
+ cc = 0 ==> go to next limb
+ */
+ while ((cc==0) && (k>=0 || kc>=0)) {
+ k--; kc--;
+ if (k>=0) {
+ if (kc>=0) cc -= mpn_sub_1(&c2, bp+k, 1, (cp[kc]>>dif) +
+ (cp[kc+1]<<(BITS_PER_MP_LIMB-dif)));
+ else /* don't forget last right chunck from c */
+ cc -= mpn_sub_1(&c2, bp+k, 1, cp[0]<<(BITS_PER_MP_LIMB-dif));
+ }
+ else { /* no more limb from b */
+ /* warning: if k was 0, kc can be negative here */
+ if ((kc+1>=0) && (cp[kc+1]<<(BITS_PER_MP_LIMB-dif))) cc=-1;
+ else while ((cc==0) && (kc>=0)) {
+ if (cp[kc]) cc=-1;
+ kc--;
+ }
+ }
+ if (cc==0) cc=c2;
}
- if ((long)cc>0) goto add_one_ulp;
- else if ((long)cc<-1) goto end_of_sub; /* the carry can be at most 1 */
- else if (kc==0) goto round_b;
+ /* cc should either 0 or -1 here */
+ if ((int)cc>0) goto add_one_ulp;
+ else if ((int)cc<0) goto end_of_sub; /* carry can be at most 1 */
+ else /* cc=0 */
+ {
+ if (c2 || (*ap & (ONE<<sh))) goto add_one_ulp;
+ else goto end_of_sub;
+ }
/* else round c: go through */
case 3: /* only c to round */
bp=cp; k=cn-k; goto to_nearest;
case 0: /* only b to round */
- round_b:
k=bn-an; dif=0; goto to_nearest;
/* otherwise the result is exact: nothing to do */
}
}
- else if ((ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
- (ISNEG(b) && rnd_mode==GMP_RNDD)) {
- cc = *ap & (((mp_limb_t)1<<sh)-1);
+ else if ((MPFR_ISNONNEG(b) && rnd_mode==GMP_RNDU) ||
+ (MPFR_ISNEG(b) && rnd_mode==GMP_RNDD)) {
+ cc = *ap & ((ONE<<sh)-1);
*ap &= ~cc; /* truncate last bits */
if (cc) goto add_one_ulp; /* will happen most of the time */
else { /* same four cases too */
@@ -331,11 +402,11 @@ mpfr_sub1(a, b, c, rnd_mode, diff_exp)
{
case 1: /* both b and c to round */
k = bn-an; /* remains k limbs from b */
- dif = diff_exp % mp_bits_per_limb;
+ dif = diff_exp % BITS_PER_MP_LIMB;
while (cc==0 && k!=0 && kc!=0) {
kc--;
cc = bp[--k] - (cp[kc]>>dif);
- if (dif) cc -= (cp[kc+1]<<(mp_bits_per_limb-dif));
+ if (dif) cc -= (cp[kc+1]<<(BITS_PER_MP_LIMB-dif));
}
if (cc) goto add_one_ulp;
else if (kc==0) goto round_b2;
@@ -343,7 +414,7 @@ mpfr_sub1(a, b, c, rnd_mode, diff_exp)
case 3: /* only c to round: nothing to do */
/* while (kc) if (cp[--kc]) goto add_one_ulp; */
/* if dif>0 : remains to check last dif bits from c */
- /* if (dif>0 && (cp[0]<<(mp_bits_per_limb-dif))) goto add_one_ulp; */
+ /* if (dif>0 && (cp[0]<<(BITS_PER_MP_LIMB-dif))) goto add_one_ulp; */
break;
case 0: /* only b to round */
round_b2:
@@ -354,22 +425,41 @@ mpfr_sub1(a, b, c, rnd_mode, diff_exp)
}
}
/* else round to zero: remove 1 ulp if neglected bits from b-c are < 0 */
- else {
- cc = *ap & (((mp_limb_t)1<<sh)-1);
+ else { int kc=cn-k;
+ cc = *ap & ((ONE<<sh)-1);
*ap &= ~cc;
if (cc==0) { /* otherwise neglected difference cannot be < 0 */
/* take into account bp[0]..bp[bn-cancel1-1] shifted by cancel2 to left
and cp[0]..cp[cn-k-1] shifted by dif bits to right */
- switch (overlap) {
+ switch (overlap) {
case 0:
case 2:
break; /* c is not truncated ==> no borrow */
case 1: /* both b and c are truncated */
+ k = bn-an; /* remains k limbs from b */
+ dif = diff_exp % BITS_PER_MP_LIMB;
+ while (k!=0 && kc!=0) {
+ kc--;
+ cc = cp[kc]>>dif;
+ if (dif) cc += cp[kc+1]<<(BITS_PER_MP_LIMB-dif);
+ k--;
+ if (bp[k]>cc) goto end_of_sub;
+ else if (bp[k]<cc) goto sub_one_ulp;
+ }
+ if (k==0) { /* is the remainder from c zero or not? */
+ while (kc!=0) {
+ kc--;
+ cc = cp[kc]>>dif;
+ if (dif) cc += cp[kc+1]<<(BITS_PER_MP_LIMB-dif);
+ if (cc) goto sub_one_ulp;
+ }
+ if (cp[0]<<(BITS_PER_MP_LIMB-dif)) goto sub_one_ulp;
+ }
break;
case 3: /* only c is truncated */
cn -= k; /* take into account cp[0]..cp[cn-1] shifted by dif bits
to the right */
- cc = (dif>0) ? cp[cn]<<(mp_bits_per_limb-dif) : 0;
+ cc = (dif>0) ? cp[cn]<<(BITS_PER_MP_LIMB-dif) : 0;
while (cc==0 && cn>0) cc = cp[--cn];
if (cc) goto sub_one_ulp;
break;
@@ -379,18 +469,18 @@ mpfr_sub1(a, b, c, rnd_mode, diff_exp)
}
goto end_of_sub;
- to_nearest: /* 0 <= sh < mp_bits_per_limb : number of bits of a to truncate
+ to_nearest: /* 0 <= sh < BITS_PER_MP_LIMB : number of bits of a to truncate
bp[k] : last significant limb from b */
#ifdef DEBUG
mpfr_print_raw(a); putchar('\n');
#endif
if (sh) {
- cc = *ap & (((mp_limb_t)1<<sh)-1);
+ cc = *ap & ((ONE<<sh)-1);
*ap &= ~cc; /* truncate last bits */
- c2 = (mp_limb_t)1<<(sh-1);
+ c2 = ONE<<(sh-1);
}
else /* no bit to truncate */
- { if (k) cc = bp[--k]; else cc = 0; c2 = (mp_limb_t)1<<(mp_bits_per_limb-1); }
+ { if (k) cc = bp[--k]; else cc = 0; c2 = ONE<<(BITS_PER_MP_LIMB-1); }
#ifdef DEBUG
printf("cc=%lu c2=%lu k=%u\n",cc,c2,k);
#endif
@@ -401,28 +491,28 @@ mpfr_print_raw(a); putchar('\n');
printf("cc=%lu\n",cc);
#endif
/* special case of rouding c shifted to the right */
- if (cc==0 && dif>0) cc=bp[0]<<(mp_bits_per_limb-dif);
+ if (cc==0 && dif>0) cc=bp[0]<<(BITS_PER_MP_LIMB-dif);
/* now if the truncated part of b = 1/2*lsb(a), check whether c=0 */
if (bp!=cp) {
- if (cc || (*ap & ((mp_limb_t)1<<sh))) goto add_one_ulp;
+ if (cc || (*ap & (ONE<<sh))) goto add_one_ulp;
}
else {
/* subtract: if cc>0, do nothing */
- if (cc==0 && (*ap & ((mp_limb_t)1<<sh))) goto add_one_ulp;
+ if (cc==0 && (*ap & (ONE<<sh))) goto add_one_ulp;
}
}
goto end_of_sub;
sub_one_ulp:
- cc = mpn_sub_1(ap, ap, an, (mp_limb_t)1<<sh);
+ cc = mpn_sub_1(ap, ap, an, ONE<<sh);
goto end_of_sub;
add_one_ulp: /* add one unit in last place to a */
- cc = mpn_add_1(ap, ap, an, (mp_limb_t)1<<sh);
+ cc = mpn_add_1(ap, ap, an, ONE<<sh);
end_of_sub:
#ifdef DEBUG
-printf("b-c="); if (SIGN(a)>0) putchar(' '); mpfr_print_raw(a); putchar('\n');
+printf("b-c="); if (MPFR_SIGN(a)>0) putchar(' '); mpfr_print_raw(a); putchar('\n');
#endif
TMP_FREE(marker);
return;
@@ -430,43 +520,78 @@ printf("b-c="); if (SIGN(a)>0) putchar(' '); mpfr_print_raw(a); putchar('\n');
void
#if __STDC__
-mpfr_sub(mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, unsigned char rnd_mode)
+mpfr_sub (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mp_rnd_t rnd_mode)
#else
-mpfr_sub(a, b, c, rnd_mode)
- mpfr_ptr a;
+mpfr_sub (a, b, c, rnd_mode)
+ mpfr_ptr a;
mpfr_srcptr b;
- mpfr_srcptr c;
- unsigned char rnd_mode;
+ mpfr_srcptr c;
+ mp_rnd_t rnd_mode;
#endif
{
int diff_exp;
- if (FLAG_NAN(b) || FLAG_NAN(c)) { SET_NAN(a); return; }
+ if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c)) {
+ MPFR_SET_NAN(a);
+ return;
+ }
+
+ MPFR_CLEAR_NAN(a);
+
+ if (MPFR_IS_INF(b))
+ {
+ if (MPFR_IS_INF(c))
+ {
+ if (MPFR_SIGN(b) != MPFR_SIGN(c))
+ {
+ MPFR_SET_INF(a);
+ if (MPFR_SIGN(a) != MPFR_SIGN(b)) { MPFR_CHANGE_SIGN(a); }
+ }
+ else
+ MPFR_SET_NAN(a);
+ }
+ else
+ {
+ MPFR_SET_INF(a);
+ if (MPFR_SIGN(b) != MPFR_SIGN(a)) { MPFR_CHANGE_SIGN(a); }
+ }
+ return;
+ }
+ else
+ if (MPFR_IS_INF(c))
+ {
+ MPFR_SET_INF(a);
+ if (MPFR_SIGN(c) == MPFR_SIGN(a)) { MPFR_CHANGE_SIGN(a); }
+ return;
+ }
+
+ if (!MPFR_NOTZERO(b)) { mpfr_neg(a, c, rnd_mode); return; }
+ if (!MPFR_NOTZERO(c)) { mpfr_set(a, b, rnd_mode); return; }
- if (!NOTZERO(b)) { mpfr_neg(a, c, rnd_mode); return; }
- if (!NOTZERO(c)) { mpfr_set(a, b, rnd_mode); return; }
+ MPFR_CLEAR_INF(a);
- diff_exp = EXP(b)-EXP(c);
- if (SIGN(b) == SIGN(c)) { /* signs are equal, it's a real subtraction */
+ diff_exp = MPFR_EXP(b)-MPFR_EXP(c);
+ if (MPFR_SIGN(b) == MPFR_SIGN(c)) {
+ /* signs are equal, it's a real subtraction */
if (diff_exp<0) {
/* exchange rounding modes towards +/- infinity */
if (rnd_mode==GMP_RNDU) rnd_mode=GMP_RNDD;
else if (rnd_mode==GMP_RNDD) rnd_mode=GMP_RNDU;
mpfr_sub1(a, c, b, rnd_mode, -diff_exp);
- CHANGE_SIGN(a);
+ MPFR_CHANGE_SIGN(a);
}
else if (diff_exp>0) mpfr_sub1(a, b, c, rnd_mode, diff_exp);
else { /* diff_exp=0 */
diff_exp = mpfr_cmp3(b,c,1);
/* if b>0 and diff_exp>0 or b<0 and diff_exp<0: abs(b) > abs(c) */
- if (diff_exp==0) SET_ZERO(a);
- else if (diff_exp*SIGN(b)>0) mpfr_sub1(a, b, c, rnd_mode, 0);
+ if (diff_exp==0) MPFR_SET_ZERO(a);
+ else if (diff_exp*MPFR_SIGN(b)>0) mpfr_sub1(a, b, c, rnd_mode, 0);
else {
/* exchange rounding modes towards +/- infinity */
if (rnd_mode==GMP_RNDU) rnd_mode=GMP_RNDD;
else if (rnd_mode==GMP_RNDD) rnd_mode=GMP_RNDU;
mpfr_sub1(a, c, b, rnd_mode, 0);
- CHANGE_SIGN(a);
+ MPFR_CHANGE_SIGN(a);
}
}
}
@@ -476,7 +601,7 @@ mpfr_sub(a, b, c, rnd_mode)
if (rnd_mode==GMP_RNDU) rnd_mode=GMP_RNDD;
else if (rnd_mode==GMP_RNDD) rnd_mode=GMP_RNDU;
mpfr_add1(a, c, b, rnd_mode, -diff_exp);
- CHANGE_SIGN(a);
+ MPFR_CHANGE_SIGN(a);
}
else mpfr_add1(a, b, c, rnd_mode, diff_exp);
}
diff --git a/mpfr/sub_ui.c b/mpfr/sub_ui.c
new file mode 100644
index 000000000..4b64caff7
--- /dev/null
+++ b/mpfr/sub_ui.c
@@ -0,0 +1,54 @@
+/* mpfr_sub_ui -- subtract a floating-point number and a machine integer
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+void
+#if __STDC__
+mpfr_sub_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mp_rnd_t rnd_mode)
+#else
+mpfr_sub_ui (y, x, u, rnd_mode)
+ mpfr_ptr y;
+ mpfr_srcptr x;
+ unsigned long int u;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ mpfr_t uu;
+ mp_limb_t up[1];
+ unsigned long cnt;
+
+ if (u) { /* if u=0, do nothing */
+ MPFR_INIT1(up, uu, BITS_PER_MP_LIMB, 1);
+ count_leading_zeros(cnt, (mp_limb_t) u);
+ *up = (mp_limb_t) u << cnt;
+ MPFR_EXP(uu) = BITS_PER_MP_LIMB-cnt;
+
+ mpfr_sub (y, x, uu, rnd_mode);
+ }
+ else
+ mpfr_set (y, x, rnd_mode);
+}
diff --git a/mpfr/swap.c b/mpfr/swap.c
new file mode 100644
index 000000000..18b6c981d
--- /dev/null
+++ b/mpfr/swap.c
@@ -0,0 +1,59 @@
+/* mpfr_swap (U, V) -- Swap U and V.
+
+Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include "gmp.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+void
+#if __STDC__
+mpfr_swap (mpfr_ptr u, mpfr_ptr v)
+#else
+mpfr_swap (u, v)
+ mpfr_ptr u;
+ mpfr_ptr v;
+#endif
+{
+ mp_ptr up, vp;
+ mp_size_t usize, vsize;
+ mp_prec_t uprec, vprec;
+ mp_exp_t uexp, vexp;
+
+ uprec = MPFR_PREC(u);
+ vprec = MPFR_PREC(v);
+ MPFR_PREC(v) = uprec;
+ MPFR_PREC(u) = vprec;
+
+ usize = MPFR_SIZE(u);
+ vsize = MPFR_SIZE(v);
+ MPFR_SIZE(v) = usize;
+ MPFR_SIZE(u) = vsize;
+
+ uexp = MPFR_EXP(u);
+ vexp = MPFR_EXP(v);
+ MPFR_EXP(v) = uexp;
+ MPFR_EXP(u) = vexp;
+
+ up = MPFR_MANT(u);
+ vp = MPFR_MANT(v);
+ MPFR_MANT(v) = up;
+ MPFR_MANT(u) = vp;
+}
diff --git a/mpfr/trunc.c b/mpfr/trunc.c
new file mode 100644
index 000000000..b6f924d35
--- /dev/null
+++ b/mpfr/trunc.c
@@ -0,0 +1,185 @@
+/* mpf_trunc, mpf_floor, mpf_ceil -- Assign a float from another float while
+ rounding it to an integer.
+
+Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+#ifdef OPERATION_floor
+#define _MPFR_FLOOR_OR_CEIL
+#define FUNC_NAME mpfr_floor
+#define MPFR_FLOOR 1
+#define MPFR_CEIL 0
+#endif
+
+#ifdef OPERATION_ceil
+#define _MPFR_FLOOR_OR_CEIL
+#define FUNC_NAME mpfr_ceil
+#define MPFR_CEIL 1
+#define MPFR_FLOOR 0
+#endif
+
+#ifdef OPERATION_trunc
+#undef FUNC_NAME
+#define FUNC_NAME mpfr_trunc
+#endif
+
+#if 0
+#ifdef _MPFR_FLOOR_OR_CEIL
+static int
+mpn_zero_p (p, n)
+ mp_ptr p;
+ mp_size_t n;
+{
+ mp_size_t i;
+
+ for (i = 0; i < n; i++)
+ {
+ if (p[i] != 0)
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+#endif
+
+void
+#if __STDC__
+FUNC_NAME (mpfr_ptr r, mpfr_srcptr u)
+#else
+FUNC_NAME (r, u)
+ mpfr_ptr r;
+ mpfr_srcptr u;
+#endif
+{
+ mp_ptr rp, up;
+ mp_size_t asize;
+ mp_size_t prec, rw;
+#ifdef _MPFR_FLOOR_OR_CEIL
+ mp_size_t ignored_n;
+#endif
+ mp_exp_t exp;
+ int signu; long diff;
+
+ if (MPFR_IS_NAN(u)) {
+ MPFR_SET_NAN(r);
+ return;
+ }
+
+ MPFR_CLEAR_NAN(r);
+
+ if (MPFR_IS_INF(u)) {
+ MPFR_SET_INF(r);
+ if (MPFR_SIGN(r) != MPFR_SIGN(u)) MPFR_CHANGE_SIGN(r);
+ return;
+ }
+
+ MPFR_CLEAR_INF(r);
+
+ if (!MPFR_NOTZERO(u)) {
+ MPFR_SET_ZERO(r);
+ return;
+ }
+
+ signu = MPFR_SIZE(u);
+ rp = MPFR_MANT(r);
+ exp = MPFR_EXP(u);
+ prec = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1;
+
+ /* Single out the case where |u| < 1. */
+ if (exp <= 0)
+ {
+#ifdef _MPFR_FLOOR_OR_CEIL
+ if ((MPFR_FLOOR && signu < 0) || (MPFR_CEIL && signu >= 0))
+ {
+ rp[prec-1] = (mp_limb_t) 1 << (BITS_PER_MP_LIMB-1);
+ MPN_ZERO(rp, prec-1);
+ /* sign of result is that of u */
+ if (MPFR_SIGN(r) * signu < 0) MPFR_CHANGE_SIGN(r);
+ MPFR_EXP(r) = 1;
+ return;
+ }
+#endif
+ MPFR_SET_ZERO(r);
+ return;
+ }
+
+ asize = (MPFR_PREC(u) - 1)/BITS_PER_MP_LIMB + 1;
+
+#ifdef _MPFR_FLOOR_OR_CEIL
+ ignored_n = 0;
+#endif
+ up = MPFR_MANT(u);
+
+ if (asize > prec)
+ {
+#ifdef _MPFR_FLOOR_OR_CEIL
+ ignored_n = asize - prec;
+#endif
+ up += asize - prec;
+ asize = prec;
+ }
+
+ diff = BITS_PER_MP_LIMB * asize - exp;
+ if (diff > 0)
+ {
+ diff = diff/BITS_PER_MP_LIMB;
+#ifdef _MPFR_FLOOR_OR_CEIL
+ ignored_n += diff;
+#endif
+ up += diff;
+ asize -= diff;
+ }
+
+ /* number of non significant bits in low limb of r */
+ rw = asize * BITS_PER_MP_LIMB - exp;
+ MPN_ZERO(rp, prec-asize);
+ rp += prec-asize;
+
+#ifdef _MPFR_FLOOR_OR_CEIL
+ if (((MPFR_FLOOR && signu < 0) || (MPFR_CEIL && signu >= 0))
+ && (!mpn_zero_p (up - ignored_n, ignored_n)
+ || (rw && (up[0] << (BITS_PER_MP_LIMB-rw)))))
+ {
+ mp_limb_t cy;
+ cy = mpn_add_1 (rp, up, asize, (mp_limb_t) 1 << rw);
+ if (cy != 0)
+ {
+ mpn_rshift(rp, rp, asize, 1);
+ rp[asize-1] = (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1);
+ exp++;
+ }
+ }
+ else
+#endif
+ MPN_COPY (rp, up, asize);
+
+ /* Put to 0 the remaining bits */
+ if (rw) rp[0] &=
+ ~((((mp_limb_t)1)<<rw) - (mp_limb_t)1);
+
+ MPFR_EXP(r) = exp;
+ if (MPFR_SIGN(r) * signu < 0) MPFR_CHANGE_SIGN(r);
+}
diff --git a/mpfr/ui_div.c b/mpfr/ui_div.c
new file mode 100644
index 000000000..712d00dd9
--- /dev/null
+++ b/mpfr/ui_div.c
@@ -0,0 +1,74 @@
+/* mpfr_ui_div -- divide a machine integer by a floating-point number
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+void
+#if __STDC__
+mpfr_ui_div (mpfr_ptr y, unsigned long int u, mpfr_srcptr x, mp_rnd_t rnd_mode)
+#else
+mpfr_ui_div (y, u, x, rnd_mode)
+ mpfr_ptr y;
+ unsigned long int u;
+ mpfr_srcptr x;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ mpfr_t uu;
+ mp_limb_t up[1];
+ unsigned long cnt;
+
+ if (MPFR_IS_NAN(x))
+ {
+ MPFR_SET_NAN(y);
+ return;
+ }
+
+ MPFR_CLEAR_NAN(y);
+
+ if (MPFR_IS_INF(x))
+ {
+ MPFR_CLEAR_INF(y);
+ MPFR_SET_ZERO(y);
+ if (MPFR_SIGN(x) != MPFR_SIGN(y)) MPFR_CHANGE_SIGN(y);
+ return;
+ }
+
+ MPFR_CLEAR_INF(y);
+
+ if (u) {
+ MPFR_INIT1(up, uu, BITS_PER_MP_LIMB, 1);
+ count_leading_zeros(cnt, (mp_limb_t) u);
+ *up = (mp_limb_t) u << cnt;
+ MPFR_EXP(uu) = BITS_PER_MP_LIMB-cnt;
+
+ mpfr_div(y, uu, x, rnd_mode);
+ }
+ else {
+ if (MPFR_IS_ZERO(x)) MPFR_SET_NAN(y); /* 0/0 */
+ else MPFR_SET_ZERO(y); /* if u=0, then set y to 0 */
+ }
+}
diff --git a/mpfr/ui_sub.c b/mpfr/ui_sub.c
new file mode 100644
index 000000000..8bc560cd6
--- /dev/null
+++ b/mpfr/ui_sub.c
@@ -0,0 +1,68 @@
+/* mpfr_ui_sub -- divide a machine integer by a floating-point number
+
+Copyright (C) 2000 Free Software Foundation.
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+void
+#if __STDC__
+mpfr_ui_sub (mpfr_ptr y, unsigned long int u, mpfr_srcptr x, mp_rnd_t rnd_mode)
+#else
+mpfr_ui_sub (y, u, x, rnd_mode)
+ mpfr_ptr y;
+ unsigned long int u;
+ mpfr_srcptr x;
+ mp_rnd_t rnd_mode;
+#endif
+{
+ mpfr_t uu;
+ mp_limb_t up[1];
+ unsigned long cnt;
+
+ if (MPFR_IS_NAN(x))
+ {
+ MPFR_SET_NAN(y);
+ return;
+ }
+
+ MPFR_CLEAR_NAN(y);
+
+ if (MPFR_IS_INF(x))
+ {
+ MPFR_SET_INF(y);
+ if (MPFR_SIGN(x) == MPFR_SIGN(y)) MPFR_CHANGE_SIGN(y);
+ return;
+ }
+
+ if (u) {
+ MPFR_INIT1(up, uu, BITS_PER_MP_LIMB, 1);
+ count_leading_zeros(cnt, (mp_limb_t) u);
+ *up = (mp_limb_t) u << cnt;
+ MPFR_EXP(uu) = BITS_PER_MP_LIMB-cnt;
+
+ mpfr_sub (y, uu, x, rnd_mode);
+ }
+ else mpfr_neg (y, x, rnd_mode); /* if u=0, then set y to -x */
+}
diff --git a/mpfr/urandomb.c b/mpfr/urandomb.c
new file mode 100644
index 000000000..02d909824
--- /dev/null
+++ b/mpfr/urandomb.c
@@ -0,0 +1,78 @@
+/* mpfr_urandomb (rop, state, nbits) -- Generate a uniform pseudorandom
+ real number between 0 (inclusive) and 1 (exclusive) of size NBITS,
+ using STATE as the random state previously initialized by a call to
+ gmp_randinit().
+
+Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the GNU MP Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+
+void
+#if __STDC__
+mpfr_urandomb (mpfr_ptr rop, gmp_randstate_t rstate)
+#else
+mpfr_urandomb (rop, rstate)
+ mpfr_ptr rop;
+ gmp_randstate_t rstate;
+#endif
+{
+ mp_ptr rp;
+ mp_size_t nlimbs;
+ mp_exp_t exp;
+ unsigned long cnt, nbits;
+
+ MPFR_CLEAR_FLAGS(rop);
+
+ rp = MPFR_MANT(rop);
+ nbits = MPFR_PREC(rop);
+ nlimbs = (nbits + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB;
+
+ _gmp_rand (rp, rstate, nbits);
+
+ /* If nbits isn't a multiple of BITS_PER_MP_LIMB, shift up. */
+ if (nlimbs != 0)
+ {
+ if (nbits % BITS_PER_MP_LIMB != 0)
+ mpn_lshift (rp, rp, nlimbs,
+ BITS_PER_MP_LIMB - nbits % BITS_PER_MP_LIMB);
+ }
+
+ exp = 0;
+ while (nlimbs != 0 && rp[nlimbs - 1] == 0)
+ {
+ nlimbs--;
+ exp--;
+ }
+
+ count_leading_zeros (cnt, rp[nlimbs - 1]);
+ if (cnt) mpn_lshift (rp, rp, nlimbs, cnt);
+ exp -= cnt;
+
+ cnt = nlimbs*BITS_PER_MP_LIMB - nbits;
+ /* cnt is the number of non significant bits in the low limb */
+ rp[0] &= ~((((mp_limb_t) 1) << cnt) - 1);
+
+ MPFR_EXP (rop) = exp;
+}