diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2002-01-25 13:43:31 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2002-01-25 13:43:31 +0000 |
commit | 3c59e080c4af2f81c2d408d73b4828f42aba04b2 (patch) | |
tree | 47bb805a769444debc25aef6e8939b99a597bd69 /sqrt.c | |
parent | 8d22d7d086ae6cba6f979b89aeb6a9e7e1d5c53c (diff) | |
download | mpfr-3c59e080c4af2f81c2d408d73b4828f42aba04b2.tar.gz |
Code reformatted.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@1670 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'sqrt.c')
-rw-r--r-- | sqrt.c | 300 |
1 files changed, 153 insertions, 147 deletions
@@ -39,6 +39,7 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, mp_rnd_t rnd_mode) int inexact = 0, t; unsigned long cc = 0; int can_round = 0; + TMP_DECL(marker0); { TMP_DECL (marker); @@ -106,176 +107,181 @@ mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, mp_rnd_t rnd_mode) to shift then. */ - TMP_MARK(marker0); - if (odd_exp_u) /* Shift u one bit to the right */ - { - if (MPFR_PREC(u) & (BITS_PER_MP_LIMB - 1)) - { - up = TMP_ALLOC(usize*BYTES_PER_MP_LIMB); - mpn_rshift(up, MPFR_MANT(u), usize, 1); - } - else - { - up = TMP_ALLOC((usize + 1)*BYTES_PER_MP_LIMB); - if (mpn_rshift(up + 1, MPFR_MANT(u), usize, 1)) - up [0] = MP_LIMB_T_HIGHBIT; - else up[0] = 0; - usize++; - } - } - - 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); - - err = rsize*BITS_PER_MP_LIMB; - if (rsize < usize) { err--; } - if (err > rrsize * BITS_PER_MP_LIMB) - { err = rrsize * BITS_PER_MP_LIMB; } + TMP_MARK(marker0); + if (odd_exp_u) /* Shift u one bit to the right */ + { + if (MPFR_PREC(u) & (BITS_PER_MP_LIMB - 1)) + { + up = TMP_ALLOC(usize * BYTES_PER_MP_LIMB); + mpn_rshift(up, MPFR_MANT(u), usize, 1); + } + else + { + up = TMP_ALLOC((usize + 1) * BYTES_PER_MP_LIMB); + if (mpn_rshift(up + 1, MPFR_MANT(u), usize, 1)) + up[0] = MP_LIMB_T_HIGHBIT; + else + up[0] = 0; + usize++; + } + } + + 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); + + err = rsize * BITS_PER_MP_LIMB; + if (rsize < usize) + err--; + if (err > rrsize * BITS_PER_MP_LIMB) + err = rrsize * BITS_PER_MP_LIMB; - tmp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); - rp = (mp_ptr) TMP_ALLOC (rrsize * BYTES_PER_MP_LIMB); - remp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + tmp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); + rp = (mp_ptr) TMP_ALLOC (rrsize * BYTES_PER_MP_LIMB); + remp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); - if (usize >= rsize) { - MPN_COPY (tmp, up + usize - rsize, rsize); - } - else { - MPN_COPY (tmp + rsize - usize, up, usize); - MPN_ZERO (tmp, rsize - usize); - } + if (usize >= rsize) + { + MPN_COPY (tmp, up + usize - rsize, rsize); + } + else + { + MPN_COPY (tmp + rsize - usize, up, usize); + MPN_ZERO (tmp, rsize - usize); + } - /* Do the real job */ + /* Do the real job */ #ifdef DEBUG - printf("Taking the sqrt of : "); - for(k = rsize - 1; k >= 0; k--) { - printf("+%lu*2^%lu",tmp[k],k*BITS_PER_MP_LIMB); } - printf(".\n"); + printf("Taking the sqrt of : "); + for(k = rsize - 1; k >= 0; k--) + printf("+%lu*2^%lu",tmp[k],k*BITS_PER_MP_LIMB); + printf(".\n"); #endif - q_limb = mpn_sqrtrem (rp, remp, tmp, rsize); + q_limb = mpn_sqrtrem (rp, remp, tmp, rsize); #ifdef DEBUG - printf ("The result is : \n"); - printf ("sqrt : "); - for (k = rrsize - 1; k >= 0; k--) - printf ("%lu ", rp[k]); - printf ("(inexact = %lu)\n", q_limb); + printf ("The result is : \n"); + printf ("sqrt : "); + for (k = rrsize - 1; k >= 0; k--) + printf ("%lu ", rp[k]); + printf ("(inexact = %lu)\n", q_limb); #endif - - can_round = mpfr_can_round_raw(rp, rrsize, 1, err, - 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 */ + can_round = mpfr_can_round_raw(rp, rrsize, 1, err, + GMP_RNDZ, rnd_mode, MPFR_PREC(r)); - if (!can_round && (rsize < 2*usize)) - { + /* If we used all the limbs of both the dividend and the divisor, + then we have the correct RNDZ rounding */ + + if (!can_round && (rsize < 2*usize)) + { #ifdef DEBUG - printf("Increasing the precision.\n"); + printf("Increasing the precision.\n"); #endif - TMP_FREE(marker); - } - } - while (!can_round && (rsize < 2*usize) - && (rsize += 2) && (rrsize ++)); + TMP_FREE(marker); + } + } + while (!can_round && (rsize < 2*usize) && (rsize += 2) && (rrsize++)); #ifdef DEBUG - printf ("can_round = %d\n", can_round); + printf ("can_round = %d\n", can_round); #endif - /* This part may be deplaced upper to avoid a few mpfr_can_round_raw */ - /* when the square root is exact. It is however very unprobable that */ - /* it would improve the behaviour of the present code on average. */ + /* This part may be deplaced upper to avoid a few mpfr_can_round_raw */ + /* when the square root is exact. It is however very unprobable that */ + /* it would improve the behaviour of the present code on average. */ - if (!q_limb) /* the sqrtrem call was exact, possible exact square root */ - { - /* if we have taken into account the whole of up */ - for (k = usize - rsize - 1; k >= 0; k ++) - if (up[k]) break; - - if (k < 0) - goto fin; /* exact square root ==> inexact = 0 */ - } - - if (can_round) - { - cc = mpfr_round_raw (rp, rp, err, 0, MPFR_PREC(r), rnd_mode, &inexact); - if (!inexact) /* exact high part: inexact flag depends from remainder */ - inexact = -q_limb; - rrsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1; - } - else - /* Use the return value of sqrtrem to decide of the rounding */ - /* Note that at this point the sqrt has been computed */ - /* EXACTLY. */ - switch (rnd_mode) + if (!q_limb) /* the sqrtrem call was exact, possible exact square root */ { - case GMP_RNDZ : - case GMP_RNDD : - inexact = -1; /* result is truncated */ - break; - - case GMP_RNDN : - /* Not in the situation ...0 111111 */ - 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 */ - (rw ? (rp[nw] >> (rw + 1)) & 1 : - (rp[nw] >> (BITS_PER_MP_LIMB - 1)) & 1))) /* or even rounding */ - { - cc = mpn_add_1 (rp + nw, rp + nw, rrsize, MP_LIMB_T_ONE << rw); - inexact = 1; - } - else - inexact = -1; - break; + /* if we have taken into account the whole of up */ + for (k = usize - rsize - 1; k >= 0; k++) + if (up[k] != 0) + break; + + if (k < 0) + goto fin; /* exact square root ==> inexact = 0 */ + } + + if (can_round) + { + cc = mpfr_round_raw (rp, rp, err, 0, MPFR_PREC(r), rnd_mode, &inexact); + if (inexact == 0) /* exact high part: inex flag depends on remainder */ + inexact = -q_limb; + rrsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1; + } + else + { + /* Use the return value of sqrtrem to decide of the rounding */ + /* Note that at this point the sqrt has been computed */ + /* EXACTLY. */ + switch (rnd_mode) + { + case GMP_RNDZ : + case GMP_RNDD : + inexact = -1; /* result is truncated */ + break; + + case GMP_RNDN : + /* Not in the situation ...0 111111 */ + rw = (MPFR_PREC(r) + 1) & (BITS_PER_MP_LIMB - 1); + if (rw != 0) + { + rw = BITS_PER_MP_LIMB - rw; + nw = 0; + } + else + nw = 1; + if ((rp[nw] >> rw) & 1 && /* Not 0111111111 */ + (q_limb || /* Nonzero remainder */ + (rw ? (rp[nw] >> (rw + 1)) & 1 : + (rp[nw] >> (BITS_PER_MP_LIMB - 1)) & 1))) /* or even r. */ + { + cc = mpn_add_1 (rp + nw, rp + nw, rrsize, MP_LIMB_T_ONE << rw); + inexact = 1; + } + else + inexact = -1; + break; - case GMP_RNDU: - /* we should arrive here only when the result is inexact, - i.e. either q_limb > 0 (the remainder from mpn_sqrtrem is non-zero) - or up[0..usize-rsize-1] is non zero, thus we have to add one - ulp, and inexact = 1 */ - inexact = 1; - t = MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1); - rsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1; - if (t) - cc = mpn_add_1 (rp + rrsize - rsize, rp + rrsize - rsize, rsize, - MP_LIMB_T_ONE << (BITS_PER_MP_LIMB - t)); - else + case GMP_RNDU: + /* we should arrive here only when the result is inexact, i.e. + either q_limb > 0 (the remainder from mpn_sqrtrem is non-zero) + or up[0..usize-rsize-1] is non zero, thus we have to add one + ulp, and inexact = 1 */ + inexact = 1; + t = MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1); + rsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1; cc = mpn_add_1 (rp + rrsize - rsize, rp + rrsize - rsize, rsize, - MP_LIMB_T_ONE); + t != 0 ? + MP_LIMB_T_ONE << (BITS_PER_MP_LIMB - t) : + MP_LIMB_T_ONE); + } } - if (cc) - { - /* Is a shift necessary here? Isn't the result 1.0000...? */ - mpn_rshift (rp, rp, rrsize, 1); - rp[rrsize-1] |= MP_LIMB_T_HIGHBIT; - MPFR_EXP(r)++; - } - - fin: - rsize = rrsize; - rrsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1; - MPN_COPY(MPFR_MANT(r), rp + rsize - rrsize, rrsize); - - if (MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1)) - MPFR_MANT(r) [0] &= ~((MP_LIMB_T_ONE << (BITS_PER_MP_LIMB - - (MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1)))) - 1) ; - - TMP_FREE (marker); + if (cc) + { + /* Is a shift necessary here? Isn't the result 1.0000...? */ + mpn_rshift (rp, rp, rrsize, 1); + rp[rrsize-1] |= MP_LIMB_T_HIGHBIT; + MPFR_EXP(r)++; + } + + fin: + rsize = rrsize; + rrsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1; + MPN_COPY(MPFR_MANT(r), rp + rsize - rrsize, rrsize); + + if (MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1)) + MPFR_MANT(r)[0] &= ~((MP_LIMB_T_ONE << + (BITS_PER_MP_LIMB - + (MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1)))) - 1); + + TMP_FREE (marker); } TMP_FREE(marker0); return inexact; |