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

Annotation of OpenXM_contrib/gmp/mpfr/div_ui.c, Revision 1.1.1.1

1.1       maekawa     1: /* mpfr_div_ui -- divide a floating-point number by a machine integer
                      2:
                      3: Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
                      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
                      8: it under the terms of the GNU Library General Public License as published by
                      9: the Free Software Foundation; either version 2 of the License, or (at your
                     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
                     14: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
                     15: License for more details.
                     16:
                     17: You should have received a copy of the GNU Library General Public License
                     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 <stdio.h>
                     23: #include "gmp.h"
                     24: #include "gmp-impl.h"
                     25: #include "longlong.h"
                     26: #include "mpfr.h"
                     27:
                     28: /* #define DEBUG */
                     29:
                     30: /* returns 0 if result exact, non-zero otherwise */
                     31: int
                     32: #ifdef __STDC__
                     33: mpfr_div_ui(mpfr_ptr y, mpfr_srcptr x, unsigned long u, unsigned char rnd_mode)
                     34: #else
                     35: mpfr_div_ui(y, x, u, rnd_mode)
                     36:      mpfr_ptr y;
                     37:      mpfr_srcptr x;
                     38:      unsigned long u;
                     39:      unsigned char rnd_mode;
                     40: #endif
                     41: {
                     42:   int xn, yn, dif, sh, i; mp_limb_t *xp, *yp, *tmp, c, d;
                     43:   TMP_DECL(marker);
                     44:
                     45:   if (FLAG_NAN(x)) { SET_NAN(y); return 1; }
                     46:   if (u==0) { printf("infinity\n"); return 1; }
                     47:
                     48:   TMP_MARK(marker);
                     49:   xn = (PREC(x)-1)/BITS_PER_MP_LIMB + 1;
                     50:   yn = (PREC(y)-1)/BITS_PER_MP_LIMB + 1;
                     51:
                     52:   xp = MANT(x);
                     53:   yp = MANT(y);
                     54:   EXP(y) = EXP(x);
                     55:   if (SIGN(x)!=SIGN(y)) CHANGE_SIGN(y);
                     56:
                     57:   dif = yn+1-xn;
                     58: #ifdef DEBUG
                     59:   printf("dif=%d u=%lu xn=%d\n",dif,u,xn);
                     60:   printf("x="); mpfr_print_raw(x); putchar('\n');
                     61: #endif
                     62:
                     63:   /* we need to store yn+1 = xn + dif limbs of the quotient */
                     64:   if (ABSSIZE(y)>=yn+1) tmp=yp;
                     65:   else tmp=TMP_ALLOC((yn+1)*BYTES_PER_MP_LIMB);
                     66:
                     67:   c = (mp_limb_t) u;
                     68:   if (dif>=0) {
                     69:     /* patch for bug in mpn_divrem_1 */
                     70: #if (UDIV_NEEDS_NORMALIZATION==1)
                     71:     count_leading_zeros(sh, c);
                     72:     c <<= sh;
                     73:     EXP(y) += sh;
                     74: #endif
                     75:     c = mpn_divrem_1(tmp, dif, xp, xn, c);
                     76:   }
                     77:   else /* dif < 0 i.e. xn > yn */
                     78:     c = mpn_divrem_1(tmp, 0, xp-dif, yn, c);
                     79:
                     80:   if (tmp[yn]==0) { tmp--; sh=0; EXP(y) -= mp_bits_per_limb; }
                     81:   /* shift left to normalize */
                     82:   count_leading_zeros(sh, tmp[yn]);
                     83:   if (sh) {
                     84:     mpn_lshift(yp, tmp+1, yn, sh);
                     85:     yp[0] += tmp[0] >> (BITS_PER_MP_LIMB-sh);
                     86:     EXP(y) -= sh;
                     87:   }
                     88:   else MPN_COPY(yp, tmp+1, yn);
                     89: #ifdef DEBUG
                     90: printf("y="); mpfr_print_raw(y); putchar('\n');
                     91: #endif
                     92:
                     93:   sh = yn*BITS_PER_MP_LIMB - PREC(y);
                     94:   /* it remains sh bits in less significant limb of y */
                     95:
                     96:   d = *yp & (((mp_limb_t)1 << sh) - 1);
                     97:   *yp ^= d; /* set to zero lowest sh bits */
                     98:
                     99:   TMP_FREE(marker);
                    100:   if ((c | d)==0) {
                    101:     for (i=0; i<-dif && xp[i]==0; i++);
                    102:     if (i>=-dif) return 0; /* result is exact */
                    103:   }
                    104:
                    105:   switch (rnd_mode) {
                    106:   case GMP_RNDZ:
                    107:     return 1; /* result is inexact */
                    108:   case GMP_RNDU:
                    109:     if (SIGN(y)>0) mpfr_add_one_ulp(y);
                    110:     return 1; /* result is inexact */
                    111:   case GMP_RNDD:
                    112:     if (SIGN(y)<0) mpfr_add_one_ulp(y);
                    113:     return 1; /* result is inexact */
                    114:   case GMP_RNDN:
                    115:     if (d < ((mp_limb_t)1 << (sh-1))) return 1;
                    116:     else if (d > ((mp_limb_t)1 << (sh-1))) {
                    117:       mpfr_add_one_ulp(y);
                    118:     }
                    119:     else { /* d = (mp_limb_t)1 << (sh-1) */
                    120:       if (c) mpfr_add_one_ulp(y);
                    121:       else {
                    122:        for (i=0; i<-dif && xp[i]==0; i++);
                    123:        if (i<-dif) mpfr_add_one_ulp(y);
                    124:        else { /* exactly in the middle */
                    125:          if (*yp & ((mp_limb_t)1 << sh)) mpfr_add_one_ulp(y);
                    126:        }
                    127:       }
                    128:     }
                    129:     return 1;
                    130:   }
                    131:   return 0; /* to prevent warning from gcc */
                    132: }
                    133:
                    134:
                    135:

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