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

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