Annotation of OpenXM/src/kan96xx/gmp-2.0.2-ssh-2/mpf/set_str.c, Revision 1.1
1.1 ! takayama 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: const 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>