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

Annotation of OpenXM_contrib/gmp/mpf/sub.c, Revision 1.1.1.3

1.1       maekawa     1: /* mpf_sub -- Subtract two floats.
                      2:
1.1.1.3 ! ohara       3: Copyright 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
        !             4: Foundation, Inc.
1.1       maekawa     5:
                      6: This file is part of the GNU MP Library.
                      7:
                      8: The GNU MP Library is free software; you can redistribute it and/or modify
1.1.1.2   maekawa     9: it under the terms of the GNU Lesser General Public License as published by
                     10: the Free Software Foundation; either version 2.1 of the License, or (at your
1.1       maekawa    11: option) any later version.
                     12:
                     13: The GNU MP Library is distributed in the hope that it will be useful, but
                     14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1.1.1.2   maekawa    15: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
1.1       maekawa    16: License for more details.
                     17:
1.1.1.2   maekawa    18: You should have received a copy of the GNU Lesser General Public License
1.1       maekawa    19: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
                     20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     21: MA 02111-1307, USA. */
                     22:
                     23: #include "gmp.h"
                     24: #include "gmp-impl.h"
                     25:
                     26: void
                     27: mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v)
                     28: {
                     29:   mp_srcptr up, vp;
                     30:   mp_ptr rp, tp;
                     31:   mp_size_t usize, vsize, rsize;
                     32:   mp_size_t prec;
                     33:   mp_exp_t exp;
                     34:   mp_size_t ediff;
                     35:   int negate;
                     36:   TMP_DECL (marker);
                     37:
                     38:   usize = u->_mp_size;
                     39:   vsize = v->_mp_size;
                     40:
                     41:   /* Handle special cases that don't work in generic code below.  */
                     42:   if (usize == 0)
                     43:     {
                     44:       mpf_neg (r, v);
                     45:       return;
                     46:     }
                     47:   if (vsize == 0)
                     48:     {
1.1.1.3 ! ohara      49:       if (r != u)
        !            50:         mpf_set (r, u);
1.1       maekawa    51:       return;
                     52:     }
                     53:
                     54:   /* If signs of U and V are different, perform addition.  */
                     55:   if ((usize ^ vsize) < 0)
                     56:     {
                     57:       __mpf_struct v_negated;
                     58:       v_negated._mp_size = -vsize;
                     59:       v_negated._mp_exp = v->_mp_exp;
                     60:       v_negated._mp_d = v->_mp_d;
                     61:       mpf_add (r, u, &v_negated);
                     62:       return;
                     63:     }
                     64:
                     65:   TMP_MARK (marker);
                     66:
                     67:   /* Signs are now known to be the same.  */
                     68:   negate = usize < 0;
                     69:
                     70:   /* Make U be the operand with the largest exponent.  */
                     71:   if (u->_mp_exp < v->_mp_exp)
                     72:     {
                     73:       mpf_srcptr t;
                     74:       t = u; u = v; v = t;
                     75:       negate ^= 1;
                     76:       usize = u->_mp_size;
                     77:       vsize = v->_mp_size;
                     78:     }
                     79:
                     80:   usize = ABS (usize);
                     81:   vsize = ABS (vsize);
                     82:   up = u->_mp_d;
                     83:   vp = v->_mp_d;
                     84:   rp = r->_mp_d;
                     85:   prec = r->_mp_prec + 1;
                     86:   exp = u->_mp_exp;
                     87:   ediff = u->_mp_exp - v->_mp_exp;
                     88:
                     89:   /* If ediff is 0 or 1, we might have a situation where the operands are
                     90:      extremely close.  We need to scan the operands from the most significant
                     91:      end ignore the initial parts that are equal.  */
                     92:   if (ediff <= 1)
                     93:     {
                     94:       if (ediff == 0)
                     95:        {
                     96:          /* Skip leading limbs in U and V that are equal.  */
                     97:          if (up[usize - 1] == vp[vsize - 1])
                     98:            {
                     99:              /* This loop normally exits immediately.  Optimize for that.  */
                    100:              do
                    101:                {
                    102:                  usize--;
                    103:                  vsize--;
                    104:                  exp--;
                    105:
                    106:                  if (usize == 0)
                    107:                    {
1.1.1.2   maekawa   108:                      if (vsize > prec)
                    109:                        {
                    110:                          vp += vsize - prec;
                    111:                          vsize = prec;
                    112:                        }
1.1       maekawa   113:                      rsize = vsize;
                    114:                      tp = (mp_ptr) vp;
                    115:                      negate ^= 1;
                    116:                      goto normalize;
                    117:                    }
                    118:                  if (vsize == 0)
                    119:                    {
1.1.1.2   maekawa   120:                      if (usize > prec)
                    121:                        {
                    122:                          up += usize - prec;
                    123:                          usize = prec;
                    124:                        }
1.1       maekawa   125:                      rsize = usize;
                    126:                      tp = (mp_ptr) up;
                    127:                      goto normalize;
                    128:                    }
                    129:                }
                    130:              while (up[usize - 1] == vp[vsize - 1]);
                    131:            }
                    132:
                    133:          if (up[usize - 1] < vp[vsize - 1])
                    134:            {
                    135:              /* For simplicity, swap U and V.  Note that since the loop above
                    136:                 wouldn't have exited unless up[usize - 1] and vp[vsize - 1]
                    137:                 were non-equal, this if-statement catches all cases where U
                    138:                 is smaller than V.  */
1.1.1.2   maekawa   139:              MPN_SRCPTR_SWAP (up,usize, vp,vsize);
1.1       maekawa   140:              negate ^= 1;
                    141:              /* negating ediff not necessary since it is 0.  */
                    142:            }
                    143:
                    144:          /* Check for
                    145:             x+1 00000000 ...
                    146:              x  ffffffff ... */
                    147:          if (up[usize - 1] != vp[vsize - 1] + 1)
                    148:            goto general_case;
                    149:          usize--;
                    150:          vsize--;
                    151:          exp--;
                    152:        }
                    153:       else /* ediff == 1 */
                    154:        {
                    155:          /* Check for
                    156:             1 00000000 ...
                    157:             0 ffffffff ... */
                    158:
1.1.1.3 ! ohara     159:          if (up[usize - 1] != 1 || vp[vsize - 1] != GMP_NUMB_MAX
1.1       maekawa   160:              || (usize >= 2 && up[usize - 2] != 0))
                    161:            goto general_case;
                    162:
                    163:          usize--;
                    164:          exp--;
                    165:        }
                    166:
                    167:       /* Skip sequences of 00000000/ffffffff */
                    168:       while (vsize != 0 && usize != 0 && up[usize - 1] == 0
1.1.1.3 ! ohara     169:             && vp[vsize - 1] == GMP_NUMB_MAX)
1.1       maekawa   170:        {
                    171:          usize--;
                    172:          vsize--;
                    173:          exp--;
                    174:        }
                    175:
                    176:       if (usize == 0)
                    177:        {
1.1.1.3 ! ohara     178:          while (vsize != 0 && vp[vsize - 1] == GMP_NUMB_MAX)
1.1       maekawa   179:            {
                    180:              vsize--;
                    181:              exp--;
                    182:            }
                    183:        }
                    184:
                    185:       if (usize > prec - 1)
                    186:        {
                    187:          up += usize - (prec - 1);
                    188:          usize = prec - 1;
                    189:        }
                    190:       if (vsize > prec - 1)
                    191:        {
                    192:          vp += vsize - (prec - 1);
                    193:          vsize = prec - 1;
                    194:        }
                    195:
                    196:       tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);
                    197:       {
                    198:        mp_limb_t cy_limb;
                    199:        if (vsize == 0)
                    200:          {
                    201:            mp_size_t size, i;
                    202:            size = usize;
                    203:            for (i = 0; i < size; i++)
                    204:              tp[i] = up[i];
                    205:            tp[size] = 1;
                    206:            rsize = size + 1;
                    207:            exp++;
                    208:            goto normalize;
                    209:          }
                    210:        if (usize == 0)
                    211:          {
                    212:            mp_size_t size, i;
                    213:            size = vsize;
                    214:            for (i = 0; i < size; i++)
1.1.1.3 ! ohara     215:              tp[i] = ~vp[i] & GMP_NUMB_MASK;
1.1       maekawa   216:            cy_limb = 1 - mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1);
                    217:            rsize = vsize;
                    218:            if (cy_limb == 0)
                    219:              {
                    220:                tp[rsize] = 1;
                    221:                rsize++;
                    222:                exp++;
                    223:              }
                    224:            goto normalize;
                    225:          }
                    226:        if (usize >= vsize)
                    227:          {
                    228:            /* uuuu     */
                    229:            /* vv       */
                    230:            mp_size_t size;
                    231:            size = usize - vsize;
                    232:            MPN_COPY (tp, up, size);
                    233:            cy_limb = mpn_sub_n (tp + size, up + size, vp, vsize);
                    234:            rsize = usize;
                    235:          }
                    236:        else /* (usize < vsize) */
                    237:          {
                    238:            /* uuuu     */
                    239:            /* vvvvvvv  */
                    240:            mp_size_t size, i;
                    241:            size = vsize - usize;
                    242:            for (i = 0; i < size; i++)
1.1.1.3 ! ohara     243:              tp[i] = ~vp[i] & GMP_NUMB_MASK;
1.1       maekawa   244:            cy_limb = mpn_sub_n (tp + size, up, vp + size, usize);
                    245:            cy_limb+= mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
                    246:            cy_limb-= mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1);
                    247:            rsize = vsize;
                    248:          }
                    249:        if (cy_limb == 0)
                    250:          {
                    251:            tp[rsize] = 1;
                    252:            rsize++;
                    253:            exp++;
                    254:          }
                    255:        goto normalize;
                    256:       }
                    257:     }
                    258:
                    259: general_case:
                    260:   /* If U extends beyond PREC, ignore the part that does.  */
                    261:   if (usize > prec)
                    262:     {
                    263:       up += usize - prec;
                    264:       usize = prec;
                    265:     }
                    266:
                    267:   /* If V extends beyond PREC, ignore the part that does.
                    268:      Note that this may make vsize negative.  */
                    269:   if (vsize + ediff > prec)
                    270:     {
                    271:       vp += vsize + ediff - prec;
                    272:       vsize = prec - ediff;
                    273:     }
                    274:
                    275:   /* Allocate temp space for the result.  Allocate
                    276:      just vsize + ediff later???  */
                    277:   tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);
                    278:
                    279:   if (ediff >= prec)
                    280:     {
                    281:       /* V completely cancelled.  */
                    282:       if (tp != up)
                    283:        MPN_COPY (rp, up, usize);
                    284:       rsize = usize;
                    285:     }
                    286:   else
                    287:     {
                    288:       /* Locate the least significant non-zero limb in (the needed
                    289:         parts of) U and V, to simplify the code below.  */
                    290:       for (;;)
                    291:        {
                    292:          if (vsize == 0)
                    293:            {
                    294:              MPN_COPY (rp, up, usize);
                    295:              rsize = usize;
                    296:              goto done;
                    297:            }
                    298:          if (vp[0] != 0)
                    299:            break;
                    300:          vp++, vsize--;
                    301:        }
                    302:       for (;;)
                    303:        {
                    304:          if (usize == 0)
                    305:            {
                    306:              MPN_COPY (rp, vp, vsize);
                    307:              rsize = vsize;
                    308:              negate ^= 1;
                    309:              goto done;
                    310:            }
                    311:          if (up[0] != 0)
                    312:            break;
                    313:          up++, usize--;
                    314:        }
                    315:
                    316:       /* uuuu     |  uuuu     |  uuuu     |  uuuu     |  uuuu    */
                    317:       /* vvvvvvv  |  vv       |    vvvvv  |    v      |       vv */
                    318:
                    319:       if (usize > ediff)
                    320:        {
                    321:          /* U and V partially overlaps.  */
                    322:          if (ediff == 0)
                    323:            {
                    324:              /* Have to compare the leading limbs of u and v
                    325:                 to determine whether to compute u - v or v - u.  */
                    326:              if (usize >= vsize)
                    327:                {
                    328:                  /* uuuu     */
                    329:                  /* vv       */
                    330:                  mp_size_t size;
                    331:                  size = usize - vsize;
                    332:                  MPN_COPY (tp, up, size);
                    333:                  mpn_sub_n (tp + size, up + size, vp, vsize);
                    334:                  rsize = usize;
                    335:                }
                    336:              else /* (usize < vsize) */
                    337:                {
                    338:                  /* uuuu     */
                    339:                  /* vvvvvvv  */
                    340:                  mp_size_t size, i;
                    341:                  size = vsize - usize;
1.1.1.3 ! ohara     342:                  tp[0] = -vp[0] & GMP_NUMB_MASK;
1.1       maekawa   343:                  for (i = 1; i < size; i++)
1.1.1.3 ! ohara     344:                    tp[i] = ~vp[i] & GMP_NUMB_MASK;
1.1       maekawa   345:                  mpn_sub_n (tp + size, up, vp + size, usize);
                    346:                  mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
                    347:                  rsize = vsize;
                    348:                }
                    349:            }
                    350:          else
                    351:            {
                    352:              if (vsize + ediff <= usize)
                    353:                {
                    354:                  /* uuuu     */
                    355:                  /*   v      */
                    356:                  mp_size_t size;
                    357:                  size = usize - ediff - vsize;
                    358:                  MPN_COPY (tp, up, size);
                    359:                  mpn_sub (tp + size, up + size, usize - size, vp, vsize);
                    360:                  rsize = usize;
                    361:                }
                    362:              else
                    363:                {
                    364:                  /* uuuu     */
                    365:                  /*   vvvvv  */
                    366:                  mp_size_t size, i;
                    367:                  size = vsize + ediff - usize;
1.1.1.3 ! ohara     368:                  tp[0] = -vp[0] & GMP_NUMB_MASK;
1.1       maekawa   369:                  for (i = 1; i < size; i++)
1.1.1.3 ! ohara     370:                    tp[i] = ~vp[i] & GMP_NUMB_MASK;
1.1       maekawa   371:                  mpn_sub (tp + size, up, usize, vp + size, usize - ediff);
                    372:                  mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
                    373:                  rsize = vsize + ediff;
                    374:                }
                    375:            }
                    376:        }
                    377:       else
                    378:        {
                    379:          /* uuuu     */
                    380:          /*      vv  */
                    381:          mp_size_t size, i;
                    382:          size = vsize + ediff - usize;
1.1.1.3 ! ohara     383:          tp[0] = -vp[0] & GMP_NUMB_MASK;
1.1       maekawa   384:          for (i = 1; i < vsize; i++)
1.1.1.3 ! ohara     385:            tp[i] = ~vp[i] & GMP_NUMB_MASK;
1.1       maekawa   386:          for (i = vsize; i < size; i++)
1.1.1.3 ! ohara     387:            tp[i] = GMP_NUMB_MAX;
1.1       maekawa   388:          mpn_sub_1 (tp + size, up, usize, (mp_limb_t) 1);
                    389:          rsize = size + usize;
                    390:        }
                    391:
                    392:     normalize:
                    393:       /* Full normalize.  Optimize later.  */
                    394:       while (rsize != 0 && tp[rsize - 1] == 0)
                    395:        {
                    396:          rsize--;
                    397:          exp--;
                    398:        }
                    399:       MPN_COPY (rp, tp, rsize);
                    400:     }
                    401:
                    402:  done:
                    403:   r->_mp_size = negate ? -rsize : rsize;
                    404:   r->_mp_exp = exp;
                    405:   TMP_FREE (marker);
                    406: }

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