diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2002-01-22 00:45:44 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2002-01-22 00:45:44 +0000 |
commit | 67b58148a1817ff4539d4a9152dcc185f6509a0f (patch) | |
tree | 89edee7b60ad573d8ee295cfe4e5b445e5c032b4 | |
parent | e643fca8156a8d7062a3c1f9709700f7c00f7833 (diff) | |
download | mpfr-67b58148a1817ff4539d4a9152dcc185f6509a0f.tar.gz |
MPFR_PREC_MAX redefined.
MPFR_INTPREC_MAX defined (internal maximum precision).
Some integer overflow detection.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@1666 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r-- | mpfr-impl.h | 6 | ||||
-rw-r--r-- | mpfr.h | 6 | ||||
-rw-r--r-- | mul.c | 9 | ||||
-rw-r--r-- | sqrt.c | 44 |
4 files changed, 40 insertions, 25 deletions
diff --git a/mpfr-impl.h b/mpfr-impl.h index bc917d5ca..8300e9e3b 100644 --- a/mpfr-impl.h +++ b/mpfr-impl.h @@ -30,6 +30,12 @@ typedef unsigned long int mp_size_unsigned_t; #define MP_LIMB_T_ONE ((mp_limb_t) 1) +#if (BITS_PER_MP_LIMB & (BITS_PER_MP_LIMB - 1)) +#error "BITS_PER_MP_LIMB must be a power of 2" +#endif + +#define MPFR_INTPREC_MAX (ULONG_MAX & ~(unsigned long) (BITS_PER_MP_LIMB - 1)) + /* Assertions */ /* Compile with -DWANT_ASSERT to check all assert statements */ @@ -58,8 +58,10 @@ MA 02111-1307, USA. */ typedef unsigned long int mp_prec_t; /* easy to change if necessary */ #define MPFR_PREC_MIN 2 -#define MPFR_PREC_MAX ULONG_MAX -typedef int mp_rnd_t; /* preferred to char */ +#define MPFR_PREC_MAX (ULONG_MAX >> 1) +/* Limit mainly due to the multiplication code. */ + +typedef int mp_rnd_t; typedef struct { mp_prec_t _mpfr_prec; /* WARNING : for the mpfr type, the precision */ @@ -136,12 +136,13 @@ mpfr_mul (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mp_rnd_t rnd_mode) bn = (bq-1)/BITS_PER_MP_LIMB + 1; /* number of significant limbs of b */ cn = (cq-1)/BITS_PER_MP_LIMB + 1; /* number of significant limbs of c */ - MPFR_ASSERTN(bq + cq >= bq); /* no integer overflow */ - tn = (bq + cq - 1) / BITS_PER_MP_LIMB + 1; - MPFR_ASSERTN((mp_size_unsigned_t) bn + cn <= MP_SIZE_T_MAX); - k = bn + cn; /* effective nb of limbs used by b*c (=tn or tn+1) */ + k = bn + cn; /* effective nb of limbs used by b*c (= tn or tn+1) below */ + + MPFR_ASSERTN(bq + cq >= bq); /* no integer overflow */ + tn = (bq + cq - 1) / BITS_PER_MP_LIMB + 1; /* <= k, thus no int overflow */ + MPFR_ASSERTN(k <= ((size_t) -1) / BYTES_PER_MP_LIMB); TMP_MARK(marker); tmp = (mp_limb_t *) TMP_ALLOC((size_t) k * BYTES_PER_MP_LIMB); @@ -34,6 +34,7 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, mp_rnd_t rnd_mode) mp_size_t rsize; mp_size_t err; mp_limb_t q_limb; + int odd_exp_u; long rw, nw, k; int inexact = 0, t; unsigned long cc = 0; @@ -81,29 +82,32 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, mp_rnd_t rnd_mode) MPFR_RET(0); /* zero is exact */ } - up = MPFR_MANT(u); - usize = (MPFR_PREC(u) - 1)/BITS_PER_MP_LIMB + 1; + up = MPFR_MANT(u); + usize = (MPFR_PREC(u) - 1)/BITS_PER_MP_LIMB + 1; #ifdef DEBUG - printf("Entering square root : "); - for(k = usize - 1; k >= 0; k--) { printf("%lu ", up[k]); } - printf(".\n"); + printf("Entering square root : "); + for(k = usize - 1; k >= 0; k--) { printf("%lu ", up[k]); } + printf(".\n"); #endif - /* Compare the mantissas */ - - 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. - Need to have 2*rrsize = rsize... - Take one extra bit if the exponent of u is odd since we shall have - to shift then. - */ + /* Compare the mantissas */ + + odd_exp_u = (unsigned int) MPFR_EXP(u) & 1; + MPFR_ASSERTN(MPFR_PREC(r) <= MPFR_INTPREC_MAX - 3); + rrsize = (MPFR_PREC(r) + 2 + odd_exp_u) / BITS_PER_MP_LIMB + 1; + MPFR_ASSERTN(rrsize <= MP_SIZE_T_MAX/2); + rsize = rrsize << 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. + Need to have 2*rrsize = rsize... + Take one extra bit if the exponent of u is odd since we shall have + to shift then. + */ TMP_MARK(marker0); - if (MPFR_EXP(u) & 1) /* Shift u one bit to the right */ + if (odd_exp_u) /* Shift u one bit to the right */ { if (MPFR_PREC(u) & (BITS_PER_MP_LIMB - 1)) { @@ -120,8 +124,10 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, mp_rnd_t rnd_mode) } } - MPFR_EXP(r) = ((MPFR_EXP(u) + (MPFR_EXP(u) & 1)) / 2) ; - + MPFR_EXP(r) = MPFR_EXP(u) != MPFR_EMAX_MAX + ? (MPFR_EXP(u) + odd_exp_u) / 2 + : (MPFR_EMAX_MAX - 1) / 2 + 1; + do { TMP_MARK (marker); |