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

Annotation of OpenXM_contrib/gmp/mpf/set_str.c, Revision 1.1.1.2

1.1       maekawa     1: /* mpf_set_str (dest, string, base) -- Convert the string STRING
                      2:    in base BASE to a float in dest.  If BASE is zero, the leading characters
                      3:    of STRING is used to figure out the base.
                      4:
1.1.1.2 ! maekawa     5: Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000 Free Software Foundation,
        !             6: Inc.
1.1       maekawa     7:
                      8: This file is part of the GNU MP Library.
                      9:
                     10: The GNU MP Library is free software; you can redistribute it and/or modify
1.1.1.2 ! maekawa    11: it under the terms of the GNU Lesser General Public License as published by
        !            12: the Free Software Foundation; either version 2.1 of the License, or (at your
1.1       maekawa    13: option) any later version.
                     14:
                     15: The GNU MP Library is distributed in the hope that it will be useful, but
                     16: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1.1.1.2 ! maekawa    17: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
1.1       maekawa    18: License for more details.
                     19:
1.1.1.2 ! maekawa    20: You should have received a copy of the GNU Lesser General Public License
1.1       maekawa    21: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
                     22: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     23: MA 02111-1307, USA. */
                     24:
                     25: #include <string.h>
                     26: #include <ctype.h>
                     27: #include "gmp.h"
                     28: #include "gmp-impl.h"
                     29: #include "longlong.h"
                     30:
1.1.1.2 ! maekawa    31:
1.1       maekawa    32: long int strtol _PROTO ((const char *, char **ptr, int));
                     33:
                     34: static int
1.1.1.2 ! maekawa    35: #if __STDC__
        !            36: digit_value_in_base (int c, int base)
        !            37: #else
1.1       maekawa    38: digit_value_in_base (c, base)
                     39:      int c;
                     40:      int base;
1.1.1.2 ! maekawa    41: #endif
1.1       maekawa    42: {
                     43:   int digit;
                     44:
                     45:   if (isdigit (c))
                     46:     digit = c - '0';
                     47:   else if (islower (c))
                     48:     digit = c - 'a' + 10;
                     49:   else if (isupper (c))
                     50:     digit = c - 'A' + 10;
                     51:   else
                     52:     return -1;
                     53:
                     54:   if (digit < base)
                     55:     return digit;
                     56:   return -1;
                     57: }
                     58:
                     59: int
                     60: #if __STDC__
                     61: mpf_set_str (mpf_ptr x, const char *str, int base)
                     62: #else
                     63: mpf_set_str (x, str, base)
                     64:      mpf_ptr x;
                     65:      char *str;
                     66:      int base;
                     67: #endif
                     68: {
                     69:   size_t str_size;
                     70:   char *s, *begs;
                     71:   size_t i;
                     72:   mp_size_t xsize;
                     73:   int c;
                     74:   int negative;
                     75:   char *dotpos = 0;
                     76:   int expflag;
                     77:   int decimal_exponent_flag;
                     78:   TMP_DECL (marker);
                     79:
                     80:   TMP_MARK (marker);
                     81:
                     82:   c = *str;
                     83:
                     84:   /* Skip whitespace.  */
                     85:   while (isspace (c))
                     86:     c = *++str;
                     87:
                     88:   negative = 0;
                     89:   if (c == '-')
                     90:     {
                     91:       negative = 1;
                     92:       c = *++str;
                     93:     }
                     94:
                     95:   decimal_exponent_flag = base < 0;
                     96:   base = ABS (base);
                     97:
1.1.1.2 ! maekawa    98:   if (digit_value_in_base (c, base == 0 ? 10 : base) < 0
        !            99:       && (c != '.' || digit_value_in_base (str[1], base == 0 ? 10 : base) < 0))
1.1       maekawa   100:     return -1;                 /* error if no digits */
                    101:
                    102:   /* If BASE is 0, try to find out the base by looking at the initial
                    103:      characters.  */
                    104:   if (base == 0)
                    105:     {
                    106:       base = 10;
                    107: #if 0
                    108:       if (c == '0')
                    109:        {
                    110:          base = 8;
1.1.1.2 ! maekawa   111:          if (str[1] == 'x' || str[1] == 'X')
        !           112:            {
        !           113:              base = 16;
        !           114:              str += 2;
        !           115:              c = *str;
        !           116:            }
1.1       maekawa   117:        }
                    118: #endif
                    119:     }
                    120:
                    121:   expflag = 0;
                    122:   str_size = strlen (str);
                    123:   for (i = 0; i < str_size; i++)
                    124:     {
                    125:       c = str[i];
                    126:       if (c == '@' || (base <= 10 && (c == 'e' || c == 'E')))
                    127:        {
                    128:          expflag = 1;
                    129:          str_size = i;
                    130:          break;
                    131:        }
                    132:
                    133:     }
                    134:
                    135:   s = begs = (char *) TMP_ALLOC (str_size + 1);
                    136:
                    137:   for (i = 0; i < str_size; i++)
                    138:     {
                    139:       c = *str;
                    140:       if (!isspace (c))
                    141:        {
                    142:          int dig;
                    143:
                    144:          if (c == '.')
                    145:            {
                    146:              if (dotpos != 0)
                    147:                {
                    148:                  TMP_FREE (marker);
                    149:                  return -1;
                    150:                }
                    151:              dotpos = s;
                    152:            }
                    153:          else
                    154:            {
                    155:              dig = digit_value_in_base (c, base);
                    156:              if (dig < 0)
                    157:                {
                    158:                  TMP_FREE (marker);
                    159:                  return -1;
                    160:                }
                    161:              *s++ = dig;
                    162:            }
                    163:        }
                    164:       c = *++str;
                    165:     }
                    166:
                    167:   str_size = s - begs;
                    168:
                    169:   xsize = str_size / __mp_bases[base].chars_per_limb + 2;
                    170:   {
                    171:     long exp_in_base;
1.1.1.2 ! maekawa   172:     mp_size_t ralloc, rsize, msize;
1.1       maekawa   173:     int cnt, i;
1.1.1.2 ! maekawa   174:     mp_ptr mp, tp, rp;
1.1       maekawa   175:     mp_exp_t exp_in_limbs;
1.1.1.2 ! maekawa   176:     mp_size_t prec = x->_mp_prec + 1;
1.1       maekawa   177:     int divflag;
1.1.1.2 ! maekawa   178:     mp_size_t madj, radj;
1.1       maekawa   179:
                    180:     mp = (mp_ptr) TMP_ALLOC (xsize * BYTES_PER_MP_LIMB);
                    181:     msize = mpn_set_str (mp, (unsigned char *) begs, str_size, base);
                    182:
                    183:     if (msize == 0)
                    184:       {
                    185:        x->_mp_size = 0;
                    186:        x->_mp_exp = 0;
                    187:        TMP_FREE (marker);
                    188:        return 0;
                    189:       }
                    190:
1.1.1.2 ! maekawa   191:     madj = 0;
        !           192:     /* Ignore excess limbs in MP,MSIZE.  */
        !           193:     if (msize > prec)
        !           194:       {
        !           195:        madj = msize - prec;
        !           196:        mp += msize - prec;
        !           197:        msize = prec;
        !           198:       }
        !           199:
1.1       maekawa   200:     if (expflag != 0)
                    201:       exp_in_base = strtol (str + 1, (char **) 0,
                    202:                            decimal_exponent_flag ? 10 : base);
                    203:     else
                    204:       exp_in_base = 0;
                    205:     if (dotpos != 0)
                    206:       exp_in_base -= s - dotpos;
                    207:     divflag = exp_in_base < 0;
                    208:     exp_in_base = ABS (exp_in_base);
                    209:
                    210:     if (exp_in_base == 0)
                    211:       {
                    212:        MPN_COPY (x->_mp_d, mp, msize);
                    213:        x->_mp_size = negative ? -msize : msize;
1.1.1.2 ! maekawa   214:        x->_mp_exp = msize + madj;
1.1       maekawa   215:        TMP_FREE (marker);
                    216:        return 0;
                    217:       }
                    218:
1.1.1.2 ! maekawa   219:     radj = 0;                  /* counts number of ignored low limbs in r */
        !           220:
        !           221:     ralloc = 2 * (prec + 1);
        !           222:     rp = (mp_ptr) TMP_ALLOC (ralloc * BYTES_PER_MP_LIMB);
        !           223:     tp = (mp_ptr) TMP_ALLOC (ralloc * BYTES_PER_MP_LIMB);
1.1       maekawa   224:
                    225:     rp[0] = base;
                    226:     rsize = 1;
                    227:     count_leading_zeros (cnt, exp_in_base);
                    228:     for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)
                    229:       {
                    230:        mpn_mul_n (tp, rp, rp, rsize);
                    231:        rsize = 2 * rsize;
                    232:        rsize -= tp[rsize - 1] == 0;
1.1.1.2 ! maekawa   233:        radj <<= 1;
        !           234:
        !           235:        if (rsize > prec)
        !           236:          {
        !           237:            radj += rsize - prec;
        !           238:            MPN_COPY_INCR (rp, tp + rsize - prec, prec);
        !           239:            rsize = prec;
        !           240:          }
        !           241:        else
        !           242:          MP_PTR_SWAP (rp, tp);
1.1       maekawa   243:
                    244:        if (((exp_in_base >> i) & 1) != 0)
                    245:          {
1.1.1.2 ! maekawa   246:            mp_limb_t cy;
1.1       maekawa   247:            cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base);
                    248:            rp[rsize] = cy;
                    249:            rsize += cy != 0;
                    250:          }
                    251:       }
                    252:
                    253:     if (rsize > prec)
                    254:       {
1.1.1.2 ! maekawa   255:        radj += rsize - prec;
1.1       maekawa   256:        rp += rsize - prec;
                    257:        rsize = prec;
                    258:       }
1.1.1.2 ! maekawa   259:
1.1       maekawa   260:     if (divflag)
                    261:       {
                    262:        mp_ptr qp;
1.1.1.2 ! maekawa   263:        mp_limb_t qlimb;
        !           264:        if (msize < rsize)
1.1       maekawa   265:          {
1.1.1.2 ! maekawa   266:            /* Pad out MP,MSIZE for current divrem semantics.  */
1.1       maekawa   267:            mp_ptr tmp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB);
                    268:            MPN_ZERO (tmp, rsize - msize);
                    269:            MPN_COPY (tmp + rsize - msize, mp, msize);
                    270:            mp = tmp;
1.1.1.2 ! maekawa   271:            madj -= rsize - msize;
1.1       maekawa   272:            msize = rsize;
                    273:          }
                    274:        count_leading_zeros (cnt, rp[rsize - 1]);
                    275:        if (cnt != 0)
                    276:          {
1.1.1.2 ! maekawa   277:            mp_limb_t cy;
1.1       maekawa   278:            mpn_lshift (rp, rp, rsize, cnt);
                    279:            cy = mpn_lshift (mp, mp, msize, cnt);
                    280:            if (cy)
                    281:              mp[msize++] = cy;
                    282:          }
1.1.1.2 ! maekawa   283:
1.1       maekawa   284:        qp = (mp_ptr) TMP_ALLOC ((prec + 1) * BYTES_PER_MP_LIMB);
1.1.1.2 ! maekawa   285:        qlimb = mpn_divrem (qp, prec - (msize - rsize), mp, msize, rp, rsize);
1.1       maekawa   286:        tp = qp;
1.1.1.2 ! maekawa   287:        exp_in_limbs = qlimb + (msize - rsize) + (madj - radj);
        !           288:        rsize = prec;
        !           289:        if (qlimb != 0)
        !           290:          {
        !           291:            tp[prec] = qlimb;
        !           292:            /* Skip the least significant limb not to overrun the destination
        !           293:               variable.  */
        !           294:            tp++;
        !           295:          }
1.1       maekawa   296:       }
                    297:     else
                    298:       {
                    299:        tp = (mp_ptr) TMP_ALLOC ((rsize + msize) * BYTES_PER_MP_LIMB);
                    300:        if (rsize > msize)
                    301:          mpn_mul (tp, rp, rsize, mp, msize);
                    302:        else
                    303:          mpn_mul (tp, mp, msize, rp, rsize);
                    304:        rsize += msize;
                    305:        rsize -= tp[rsize - 1] == 0;
1.1.1.2 ! maekawa   306:        exp_in_limbs = rsize + madj + radj;
1.1       maekawa   307:
                    308:        if (rsize > prec)
                    309:          {
                    310:            tp += rsize - prec;
                    311:            rsize = prec;
                    312:            exp_in_limbs += 0;
                    313:          }
                    314:       }
                    315:
                    316:     MPN_COPY (x->_mp_d, tp, rsize);
                    317:     x->_mp_size = negative ? -rsize : rsize;
                    318:     x->_mp_exp = exp_in_limbs;
                    319:     TMP_FREE (marker);
                    320:     return 0;
                    321:   }
                    322: }

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