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

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

1.1       ohara       1: /* mpfr_cmp2 -- exponent shift when subtracting two numbers.
                      2:
                      3: Copyright 1999, 2000, 2001 Free Software Foundation.
                      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 Lesser General Public License as published by
                      9: the Free Software Foundation; either version 2.1 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 Lesser General Public
                     15: License for more details.
                     16:
                     17: You should have received a copy of the GNU Lesser 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 "gmp.h"
                     23: #include "gmp-impl.h"
                     24: #include "longlong.h"
                     25: #include "mpfr.h"
                     26: #include "mpfr-impl.h"
                     27:
                     28: /* Returns the number of canceled bits when one subtracts |c| from |b|
                     29:    if |b| != |c|, and the sign.
                     30:
                     31:    Assumes neither of b or c is NaN or +/- infinity.
                     32:
                     33:    In other terms, if |b| != |c|, mpfr_cmp2 (b, c) returns
                     34:    EXP(max(|b|,|c|)) - EXP(|b| - |c|).
                     35: */
                     36:
                     37: int
                     38: mpfr_cmp2 (mpfr_srcptr b, mpfr_srcptr c, mp_prec_t *cancel)
                     39: {
                     40:   mp_limb_t *bp, *cp, bb, cc = 0, lastc = 0, dif, high_dif = 0;
                     41:   mp_size_t bn, cn;
                     42:   mp_exp_unsigned_t diff_exp;
                     43:   mp_prec_t res = 0;
                     44:   int sign;
                     45:
                     46:   MPFR_ASSERTN(MPFR_IS_FP(b));
                     47:   MPFR_ASSERTN(MPFR_IS_FP(c));
                     48:
                     49:   /* Optimized case x - x */
                     50:   if (b == c)
                     51:     return 0;
                     52:
                     53:   if (MPFR_IS_ZERO(b))
                     54:     {
                     55:       if (MPFR_IS_ZERO(c))
                     56:         return 0;
                     57:
                     58:       *cancel = 0;
                     59:       return -1;
                     60:     }
                     61:
                     62:   if (MPFR_IS_ZERO(c))
                     63:     {
                     64:       *cancel = 0;
                     65:       return 1;
                     66:     }
                     67:
                     68:   if (MPFR_EXP(b) >= MPFR_EXP(c))
                     69:     {
                     70:       sign = 1;
                     71:       diff_exp = (mp_exp_unsigned_t) MPFR_EXP(b) - MPFR_EXP(c);
                     72:
                     73:       bp = MPFR_MANT(b);
                     74:       cp = MPFR_MANT(c);
                     75:
                     76:       bn = (MPFR_PREC(b) - 1) / BITS_PER_MP_LIMB;
                     77:       cn = (MPFR_PREC(c) - 1) / BITS_PER_MP_LIMB;
                     78:
                     79:       if (diff_exp == 0)
                     80:         {
                     81:           while (bn >= 0 && cn >= 0 && bp[bn] == cp[cn])
                     82:             {
                     83:               bn--;
                     84:               cn--;
                     85:               res += BITS_PER_MP_LIMB;
                     86:             }
                     87:
                     88:           if (bn < 0)
                     89:             {
                     90:               if (cn < 0) /* b = c */
                     91:                 return 0;
                     92:
                     93:               bp = cp;
                     94:               bn = cn;
                     95:               cn = -1;
                     96:               sign = -1;
                     97:             }
                     98:
                     99:           if (cn < 0) /* c discards exactly the upper part of b */
                    100:             {
                    101:               unsigned int z;
                    102:
                    103:               MPFR_ASSERTN(bn >= 0);
                    104:
                    105:               while (bp[bn] == 0)
                    106:                 {
                    107:                   if (--bn < 0) /* b = c */
                    108:                     return 0;
                    109:                   res += BITS_PER_MP_LIMB;
                    110:                 }
                    111:
                    112:               count_leading_zeros(z, bp[bn]); /* bp[bn] <> 0 */
                    113:               *cancel = res + z;
                    114:               return sign;
                    115:             }
                    116:
                    117:           MPFR_ASSERTN(bn >= 0);
                    118:           MPFR_ASSERTN(cn >= 0);
                    119:           MPFR_ASSERTN(bp[bn] != cp[cn]);
                    120:           if (bp[bn] < cp[cn])
                    121:             {
                    122:               mp_limb_t *tp;
                    123:               mp_size_t tn;
                    124:
                    125:               tp = bp; bp = cp; cp = tp;
                    126:               tn = bn; bn = cn; cn = tn;
                    127:               sign = -1;
                    128:             }
                    129:         }
                    130:     } /* MPFR_EXP(b) >= MPFR_EXP(c) */
                    131:   else /* MPFR_EXP(b) < MPFR_EXP(c) */
                    132:     {
                    133:       sign = -1;
                    134:       diff_exp = (mp_exp_unsigned_t) MPFR_EXP(c) - MPFR_EXP(b);
                    135:
                    136:       bp = MPFR_MANT(c);
                    137:       cp = MPFR_MANT(b);
                    138:
                    139:       bn = (MPFR_PREC(c) - 1) / BITS_PER_MP_LIMB;
                    140:       cn = (MPFR_PREC(b) - 1) / BITS_PER_MP_LIMB;
                    141:     }
                    142:
                    143:   /* now we have removed the identical upper limbs of b and c
                    144:      (can happen only when diff_exp = 0), and after the possible
                    145:      swap, we have |b| > |c|: bp[bn] > cc, bn >= 0, cn >= 0 */
                    146:
                    147:   if (diff_exp < BITS_PER_MP_LIMB)
                    148:     {
                    149:       cc = cp[cn] >> diff_exp;
                    150:       /* warning: a shift by BITS_PER_MP_LIMB may give wrong results */
                    151:       if (diff_exp)
                    152:         lastc = cp[cn] << (BITS_PER_MP_LIMB - diff_exp);
                    153:       cn--;
                    154:     }
                    155:   else
                    156:     diff_exp -= BITS_PER_MP_LIMB;
                    157:
                    158:   dif = bp[bn--] - cc; /* necessarily dif >= 1 */
                    159:
                    160:   while ((cn >= 0 || lastc != 0) && (high_dif == 0) && (dif == 1))
                    161:     { /* dif=1 implies diff_exp = 0 or 1 */
                    162:       bb = (bn >= 0) ? bp[bn] : 0;
                    163:       cc = lastc;
                    164:       if (cn >= 0)
                    165:        {
                    166:           if (diff_exp == 0)
                    167:             {
                    168:               cc += cp[cn];
                    169:             }
                    170:           else /* diff_exp = 1 */
                    171:             {
                    172:               cc += cp[cn] >> 1;
                    173:               lastc = cp[cn] << (BITS_PER_MP_LIMB - 1);
                    174:             }
                    175:        }
                    176:       else
                    177:        lastc = 0;
                    178:       high_dif = 1 - mpn_sub_n (&dif, &bb, &cc, 1);
                    179:       bn--;
                    180:       cn--;
                    181:       res += BITS_PER_MP_LIMB;
                    182:     }
                    183:
                    184:   /* (cn<0 and lastc=0) or (high_dif,dif)<>(0,1) */
                    185:
                    186:   if (high_dif != 0) /* necessarily high_dif = 1 */
                    187:     {
                    188:       res--;
                    189:       if (dif != 0)
                    190:         {
                    191:           *cancel = res;
                    192:           return sign;
                    193:         }
                    194:     }
                    195:   else /* high_dif = 0 */
                    196:     {
                    197:       unsigned int z;
                    198:
                    199:       count_leading_zeros(z, dif); /* dif > 1 here */
                    200:       res += z;
                    201:       if (dif != (MP_LIMB_T_ONE << (BITS_PER_MP_LIMB - z - 1)))
                    202:         { /* dif is not a power of two */
                    203:           *cancel = res;
                    204:           return sign;
                    205:         }
                    206:     }
                    207:
                    208:   /* now result is res + (low(b) < low(c)) */
                    209:   while (bn >= 0 && (cn >= 0 || lastc != 0))
                    210:     {
                    211:       if (diff_exp >= BITS_PER_MP_LIMB)
                    212:        diff_exp -= BITS_PER_MP_LIMB;
                    213:       else
                    214:        {
                    215:          cc = lastc;
                    216:          if (cn >= 0)
                    217:            {
                    218:              cc += cp[cn] >> diff_exp;
                    219:              if (diff_exp != 0)
                    220:                 lastc = cp[cn] << (BITS_PER_MP_LIMB - diff_exp);
                    221:            }
                    222:          else
                    223:            lastc = 0;
                    224:          cn--;
                    225:        }
                    226:       if (bp[bn] != cc)
                    227:         {
                    228:           *cancel = res + (bp[bn] < cc);
                    229:           return sign;
                    230:         }
                    231:       bn--;
                    232:     }
                    233:
                    234:   if (bn < 0)
                    235:     {
                    236:       if (lastc != 0)
                    237:         res++;
                    238:       else
                    239:         {
                    240:           while (cn >= 0 && cp[cn] == 0)
                    241:             cn--;
                    242:           if (cn >= 0)
                    243:             res++;
                    244:         }
                    245:     }
                    246:
                    247:   *cancel = res;
                    248:   return sign;
                    249: }

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