[BACK]Return to sqrt.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpfr

Annotation of OpenXM_contrib/gmp/mpfr/sqrt.c, Revision 1.1.1.2

1.1       maekawa     1: /* mpfr_sqrt -- square root of a floating-point number
                      2:
1.1.1.2 ! ohara       3: Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
1.1       maekawa     4:
                      5: This file is part of the MPFR Library.
                      6:
                      7: The MPFR Library is free software; you can redistribute it and/or modify
1.1.1.2 ! ohara       8: it under the terms of the GNU Lesser General Public License as published by
        !             9: the Free Software Foundation; either version 2.1 of the License, or (at your
1.1       maekawa    10: option) any later version.
                     11:
                     12: The MPFR Library is distributed in the hope that it will be useful, but
                     13: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1.1.1.2 ! ohara      14: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
1.1       maekawa    15: License for more details.
                     16:
1.1.1.2 ! ohara      17: You should have received a copy of the GNU Lesser General Public License
1.1       maekawa    18: along with the MPFR Library; see the file COPYING.LIB.  If not, write to
                     19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     20: MA 02111-1307, USA. */
                     21:
                     22: #include "gmp.h"
                     23: #include "gmp-impl.h"
                     24: #include "mpfr.h"
1.1.1.2 ! ohara      25: #include "mpfr-impl.h"
1.1       maekawa    26:
                     27: /* #define DEBUG */
                     28:
                     29: int
1.1.1.2 ! ohara      30: mpfr_sqrt (mpfr_ptr r, mpfr_srcptr u, mp_rnd_t rnd_mode)
1.1       maekawa    31: {
                     32:   mp_ptr up, rp, tmp, remp;
                     33:   mp_size_t usize, rrsize;
                     34:   mp_size_t rsize;
1.1.1.2 ! ohara      35:   mp_size_t err;
1.1       maekawa    36:   mp_limb_t q_limb;
1.1.1.2 ! ohara      37:   int odd_exp_u;
1.1       maekawa    38:   long rw, nw, k;
1.1.1.2 ! ohara      39:   int inexact = 0, t;
1.1       maekawa    40:   unsigned long cc = 0;
1.1.1.2 ! ohara      41:   int can_round = 0;
1.1       maekawa    42:
1.1.1.2 ! ohara      43:   TMP_DECL(marker);
1.1       maekawa    44:
1.1.1.2 ! ohara      45:     if (MPFR_IS_NAN(u))
        !            46:       {
        !            47:         MPFR_SET_NAN(r);
        !            48:         MPFR_RET_NAN;
        !            49:       }
        !            50:
        !            51:     if (MPFR_SIGN(u) < 0)
        !            52:       {
        !            53:         if (MPFR_IS_INF(u) || MPFR_NOTZERO(u))
        !            54:           {
        !            55:             MPFR_SET_NAN(r);
        !            56:             MPFR_RET_NAN;
        !            57:           }
        !            58:         else
        !            59:           { /* sqrt(-0) = -0 */
        !            60:             MPFR_CLEAR_FLAGS(r);
        !            61:             MPFR_SET_ZERO(r);
        !            62:             MPFR_SET_NEG(r);
        !            63:             MPFR_RET(0);
        !            64:           }
        !            65:       }
        !            66:
        !            67:     MPFR_CLEAR_NAN(r);
        !            68:     MPFR_SET_POS(r);
        !            69:
        !            70:     if (MPFR_IS_INF(u))
        !            71:       {
        !            72:         MPFR_SET_INF(r);
        !            73:         MPFR_RET(0);
        !            74:       }
        !            75:
        !            76:     MPFR_CLEAR_INF(r);
        !            77:
        !            78:     if (MPFR_IS_ZERO(u))
        !            79:       {
        !            80:         MPFR_SET_ZERO(r);
        !            81:         MPFR_RET(0); /* zero is exact */
        !            82:       }
        !            83:
        !            84:     up = MPFR_MANT(u);
        !            85:     usize = (MPFR_PREC(u) - 1)/BITS_PER_MP_LIMB + 1;
1.1       maekawa    86:
                     87: #ifdef DEBUG
1.1.1.2 ! ohara      88:     printf("Entering square root : ");
        !            89:     for(k = usize - 1; k >= 0; k--) { printf("%lu ", up[k]); }
        !            90:     printf(".\n");
1.1       maekawa    91: #endif
                     92:
1.1.1.2 ! ohara      93:     /* Compare the mantissas */
1.1       maekawa    94:
1.1.1.2 ! ohara      95:     odd_exp_u = (unsigned int) MPFR_EXP(u) & 1;
        !            96:     MPFR_ASSERTN(MPFR_PREC(r) <= MPFR_INTPREC_MAX - 3);
        !            97:     rrsize = (MPFR_PREC(r) + 2 + odd_exp_u) / BITS_PER_MP_LIMB + 1;
        !            98:     MPFR_ASSERTN(rrsize <= MP_SIZE_T_MAX/2);
        !            99:     rsize = rrsize << 1;
        !           100:     /* One extra bit is needed in order to get the square root with enough
        !           101:        precision ; take one extra bit for rrsize in order to solve more
        !           102:        easily the problem of rounding to nearest.
        !           103:        Need to have 2*rrsize = rsize...
        !           104:        Take one extra bit if the exponent of u is odd since we shall have
        !           105:        to shift then.
        !           106:     */
        !           107:
        !           108:     TMP_MARK(marker);
        !           109:     if (odd_exp_u) /* Shift u one bit to the right */
        !           110:       {
        !           111:         if (MPFR_PREC(u) & (BITS_PER_MP_LIMB - 1))
        !           112:           {
        !           113:             up = TMP_ALLOC(usize * BYTES_PER_MP_LIMB);
        !           114:             mpn_rshift(up, MPFR_MANT(u), usize, 1);
        !           115:           }
        !           116:         else
        !           117:           {
        !           118:             up = TMP_ALLOC((usize + 1) * BYTES_PER_MP_LIMB);
        !           119:             if (mpn_rshift(up + 1, MPFR_MANT(u), usize, 1))
        !           120:               up[0] = GMP_LIMB_HIGHBIT;
        !           121:             else
        !           122:               up[0] = 0;
        !           123:             usize++;
        !           124:           }
1.1       maekawa   125:       }
                    126:
1.1.1.2 ! ohara     127:     MPFR_EXP(r) = MPFR_EXP(u) != MPFR_EMAX_MAX
        !           128:       ? (MPFR_EXP(u) + odd_exp_u) / 2
        !           129:       : (MPFR_EMAX_MAX - 1) / 2 + 1;
        !           130:
        !           131:     do
        !           132:       {
        !           133:
        !           134:         err = rsize * BITS_PER_MP_LIMB;
        !           135:         if (rsize < usize)
        !           136:           err--;
        !           137:         if (err > rrsize * BITS_PER_MP_LIMB)
        !           138:           err = rrsize * BITS_PER_MP_LIMB;
        !           139:
        !           140:         tmp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
        !           141:         rp = (mp_ptr) TMP_ALLOC (rrsize * BYTES_PER_MP_LIMB);
        !           142:         remp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
        !           143:
        !           144:         if (usize >= rsize)
        !           145:           {
        !           146:             MPN_COPY (tmp, up + usize - rsize, rsize);
        !           147:           }
        !           148:         else
        !           149:           {
        !           150:             MPN_COPY (tmp + rsize - usize, up, usize);
        !           151:             MPN_ZERO (tmp, rsize - usize);
        !           152:           }
        !           153:
        !           154:         /* Do the real job */
1.1       maekawa   155:
                    156: #ifdef DEBUG
1.1.1.2 ! ohara     157:         printf("Taking the sqrt of : ");
        !           158:         for(k = rsize - 1; k >= 0; k--)
        !           159:           printf("+%lu*2^%lu",tmp[k],k*BITS_PER_MP_LIMB);
        !           160:         printf(".\n");
1.1       maekawa   161: #endif
                    162:
1.1.1.2 ! ohara     163:         q_limb = mpn_sqrtrem (rp, remp, tmp, rsize);
1.1       maekawa   164:
                    165: #ifdef DEBUG
1.1.1.2 ! ohara     166:         printf ("The result is : \n");
        !           167:         printf ("sqrt : ");
        !           168:         for (k = rrsize - 1; k >= 0; k--)
        !           169:           printf ("%lu ", rp[k]);
        !           170:         printf ("(inexact = %lu)\n", q_limb);
1.1       maekawa   171: #endif
                    172:
1.1.1.2 ! ohara     173:         can_round = mpfr_can_round_raw(rp, rrsize, 1, err,
        !           174:                                        GMP_RNDZ, rnd_mode, MPFR_PREC(r));
1.1       maekawa   175:
1.1.1.2 ! ohara     176:         /* If we used all the limbs of both the dividend and the divisor,
        !           177:            then we have the correct RNDZ rounding */
        !           178:
        !           179:         if (!can_round && (rsize < 2*usize))
        !           180:           {
1.1       maekawa   181: #ifdef DEBUG
1.1.1.2 ! ohara     182:             printf("Increasing the precision.\n");
        !           183: #endif
        !           184:           }
        !           185:       }
        !           186:     while (!can_round && (rsize < 2*usize) && (rsize += 2) && (rrsize++));
        !           187: #ifdef DEBUG
        !           188:     printf ("can_round = %d\n", can_round);
1.1       maekawa   189: #endif
                    190:
1.1.1.2 ! ohara     191:     /* This part may be deplaced upper to avoid a few mpfr_can_round_raw */
        !           192:     /* when the square root is exact. It is however very unprobable that */
        !           193:     /* it would improve the behaviour of the present code on average.    */
        !           194:
        !           195:     if (!q_limb) /* the sqrtrem call was exact, possible exact square root */
        !           196:       {
        !           197:         /* if we have taken into account the whole of up */
        !           198:         for (k = usize - rsize - 1; k >= 0; k++)
        !           199:           if (up[k] != 0)
        !           200:             break;
        !           201:
        !           202:         if (k < 0)
        !           203:           goto fin; /* exact square root ==> inexact = 0 */
        !           204:       }
        !           205:
        !           206:     if (can_round)
        !           207:       {
        !           208:         cc = mpfr_round_raw (rp, rp, err, 0, MPFR_PREC(r), rnd_mode, &inexact);
        !           209:         if (inexact == 0) /* exact high part: inex flag depends on remainder */
        !           210:           inexact = -q_limb;
        !           211:         rrsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1;
        !           212:       }
        !           213:     else
        !           214:       {
        !           215:         /* Use the return value of sqrtrem to decide of the rounding */
        !           216:         /* Note that at this point the sqrt has been computed        */
        !           217:         /* EXACTLY.                                                  */
        !           218:         switch (rnd_mode)
        !           219:           {
        !           220:           case GMP_RNDZ :
        !           221:           case GMP_RNDD :
        !           222:             inexact = -1; /* result is truncated */
        !           223:             break;
        !           224:
        !           225:           case GMP_RNDN :
        !           226:             /* Not in the situation ...0 111111 */
        !           227:             rw = (MPFR_PREC(r) + 1) & (BITS_PER_MP_LIMB - 1);
        !           228:             if (rw != 0)
        !           229:               {
        !           230:                 rw = BITS_PER_MP_LIMB - rw;
        !           231:                 nw = 0;
        !           232:               }
        !           233:             else
        !           234:               nw = 1;
        !           235:             if ((rp[nw] >> rw) & 1 &&          /* Not 0111111111 */
        !           236:                 (q_limb ||                     /* Nonzero remainder */
        !           237:                  (rw ? (rp[nw] >> (rw + 1)) & 1 :
        !           238:                   (rp[nw] >> (BITS_PER_MP_LIMB - 1)) & 1))) /* or even r. */
        !           239:               {
        !           240:                 cc = mpn_add_1 (rp + nw, rp + nw, rrsize, MP_LIMB_T_ONE << rw);
        !           241:                 inexact = 1;
        !           242:               }
        !           243:             else
        !           244:               inexact = -1;
        !           245:             break;
1.1       maekawa   246:
1.1.1.2 ! ohara     247:           case GMP_RNDU:
        !           248:             /* we should arrive here only when the result is inexact, i.e.
        !           249:                either q_limb > 0 (the remainder from mpn_sqrtrem is non-zero)
        !           250:                or up[0..usize-rsize-1] is non zero, thus we have to add one
        !           251:                ulp, and inexact = 1 */
        !           252:             inexact = 1;
        !           253:             t = MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1);
        !           254:             rsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1;
        !           255:            cc = mpn_add_1 (rp + rrsize - rsize, rp + rrsize - rsize, rsize,
        !           256:                             t != 0 ?
        !           257:                             MP_LIMB_T_ONE << (BITS_PER_MP_LIMB - t) :
        !           258:                             MP_LIMB_T_ONE);
        !           259:           }
1.1       maekawa   260:       }
                    261:
1.1.1.2 ! ohara     262:     if (cc)
        !           263:       {
        !           264:         /* Is a shift necessary here? Isn't the result 1.0000...? */
        !           265:         mpn_rshift (rp, rp, rrsize, 1);
        !           266:         rp[rrsize-1] |= GMP_LIMB_HIGHBIT;
        !           267:         MPFR_EXP(r)++;
        !           268:       }
1.1       maekawa   269:
                    270:  fin:
1.1.1.2 ! ohara     271:     rsize = rrsize;
        !           272:     rrsize = (MPFR_PREC(r) - 1)/BITS_PER_MP_LIMB + 1;
        !           273:     MPN_COPY(MPFR_MANT(r), rp + rsize - rrsize, rrsize);
        !           274:
        !           275:     if (MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1))
        !           276:       MPFR_MANT(r)[0] &= ~((MP_LIMB_T_ONE <<
        !           277:                             (BITS_PER_MP_LIMB -
        !           278:                              (MPFR_PREC(r) & (BITS_PER_MP_LIMB - 1)))) - 1);
        !           279:
        !           280:   TMP_FREE(marker);
        !           281:   return inexact;
1.1       maekawa   282: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>