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

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

1.1       ohara       1: /* mpfr_set_str -- set a floating-point number from a string
                      2:
                      3: Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
                      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 <ctype.h>
                     23: #include <stdio.h>
                     24: #include <stdlib.h>
                     25: #include <limits.h>
                     26: #include <errno.h>
                     27:
                     28: #ifdef HAVE_STRCASECMP
                     29: #include <string.h>
                     30: #else
                     31: int strcasecmp (const char *, const char *);
                     32: #endif
                     33:
                     34: #include "gmp.h"
                     35: #include "gmp-impl.h"
                     36: #include "longlong.h"
                     37: #include "mpfr.h"
                     38: #include "mpfr-impl.h"
                     39:
                     40: int
                     41: mpfr_set_str (mpfr_ptr x, __gmp_const char *str, int base, mp_rnd_t rnd_mode)
                     42: {
                     43:   mpz_t mantissa;
                     44:   int negative, inex;
                     45:   long k = 0;
                     46:   unsigned char c;
                     47:   long e;
                     48:   mp_prec_t q;
                     49:   mpfr_t y, z;
                     50:
                     51:   if (base < 2 || base > 36)
                     52:     return 1;
                     53:
                     54:   if (strcasecmp(str, "NaN") == 0)
                     55:     {
                     56:       MPFR_SET_NAN(x);
                     57:       /* MPFR_RET_NAN not used as the return value isn't a ternary value */
                     58:       __mpfr_flags |= MPFR_FLAGS_NAN;
                     59:       return 0;
                     60:     }
                     61:
                     62:   negative = *str == '-';
                     63:   if (negative || *str == '+')
                     64:     str++;
                     65:
                     66:   if (strcasecmp(str, "Inf") == 0)
                     67:     {
                     68:       MPFR_CLEAR_NAN(x);
                     69:       MPFR_SET_INF(x);
                     70:       if (negative)
                     71:         MPFR_SET_NEG(x);
                     72:       else
                     73:         MPFR_SET_POS(x);
                     74:       return 0;
                     75:     }
                     76:
                     77:   mpz_init(mantissa);
                     78:   mpz_set_ui(mantissa, 0);
                     79:
                     80:   while (*str == '0')
                     81:     str++; /* skip initial zeros */
                     82:
                     83:   /* allowed characters are '0' to '0'+base-1 if base <= 10,
                     84:      and '0' to '9' plus 'a' to 'a'+base-11 if 10 < base <= 36 */
                     85:   while (c = *str,
                     86:          (isdigit(c) && c < '0' + base) ||
                     87:          (islower(c) && c < 'a'-10 + base))
                     88:     {
                     89:       str++;
                     90:       mpz_mul_ui(mantissa, mantissa, base);
                     91:       mpz_add_ui(mantissa, mantissa, isdigit(c) ? c - '0' : c - ('a'-10));
                     92:     }
                     93:
                     94:   /* k is the number of non-zero digits before the decimal point */
                     95:
                     96:   if (*str == '.')
                     97:     {
                     98:       str++;
                     99:       while (c = *str,
                    100:              (isdigit(c) && c < '0' + base) ||
                    101:              (islower(c) && c < 'a'-10 + base))
                    102:        {
                    103:           if (k == LONG_MAX)
                    104:             {
                    105:               mpz_clear(mantissa);
                    106:               return -1;
                    107:             }
                    108:          k++;
                    109:          str++;
                    110:           mpz_mul_ui(mantissa, mantissa, base);
                    111:           mpz_add_ui(mantissa, mantissa, isdigit(c) ? c - '0' : c - ('a'-10));
                    112:        }
                    113:     }
                    114:
                    115:   if (*str == '\0') /* no exponent */
                    116:     {
                    117:       e = -k;
                    118:     }
                    119:   else if ((base <= 10 && (*str == 'e' || *str == 'E')) || *str == '@')
                    120:     {
                    121:       char *endptr;
                    122:
                    123:       if (*++str == '\0') /* exponent character but no exponent */
                    124:         {
                    125:           mpz_clear(mantissa);
                    126:           return 1;
                    127:         }
                    128:
                    129:       errno = 0;
                    130:       e = strtol(str, &endptr, 10); /* signed exponent after 'e', 'E' or '@' */
                    131:       if (*endptr != '\0')
                    132:         {
                    133:           mpz_clear(mantissa);
                    134:           return 1;
                    135:         }
                    136:       if (errno)
                    137:         {
                    138:           mpz_clear(mantissa);
                    139:           return -1;
                    140:         }
                    141:
                    142:       if (e < 0 && (unsigned long) e - k < (unsigned long) LONG_MIN)
                    143:         {
                    144:           mpz_clear(mantissa);
                    145:           return -1;
                    146:         }
                    147:       e -= k;
                    148:     }
                    149:   else /* unexpected character */
                    150:     {
                    151:       mpz_clear(mantissa);
                    152:       return 1;
                    153:     }
                    154:
                    155:   /* the number is mantissa*base^expn */
                    156:
                    157:   q = MPFR_PREC(x) & ~(mp_prec_t) (BITS_PER_MP_LIMB - 1);
                    158:   mpfr_init(y);
                    159:   mpfr_init(z);
                    160:
                    161:   do
                    162:     {
                    163:       q += BITS_PER_MP_LIMB;
                    164:       mpfr_set_prec(y, q);
                    165:       mpfr_set_z(y, mantissa, GMP_RNDN); /* error <= 1/2*ulp(y) */
                    166:
                    167:       mpfr_set_prec(z, q);
                    168:       if (e > 0)
                    169:         {
                    170:           inex = mpfr_ui_pow_ui(z, base, e, GMP_RNDN);
                    171:           mpfr_mul(y, y, z, GMP_RNDN);
                    172:         }
                    173:       else if (e < 0)
                    174:         {
                    175:           inex = mpfr_ui_pow_ui(z, base, -e, GMP_RNDN);
                    176:           mpfr_div(y, y, z, GMP_RNDN);
                    177:         }
                    178:       else
                    179:         inex = 1;
                    180:       if (negative)
                    181:         mpfr_neg(y, y, GMP_RNDN);
                    182:     }
                    183:   while (mpfr_can_round(y, q-inex, GMP_RNDN, rnd_mode, MPFR_PREC(x))==0
                    184:          && q<=2*MPFR_PREC(x));
                    185:
                    186:   mpfr_set(x, y, rnd_mode);
                    187:
                    188:   mpz_clear(mantissa);
                    189:   mpfr_clear(y);
                    190:   mpfr_clear(z);
                    191:   return 0;
                    192: }
                    193:
                    194: int
                    195: mpfr_init_set_str (mpfr_ptr x, char *str, int base, mp_rnd_t rnd_mode)
                    196: {
                    197:   mpfr_init (x);
                    198:   return mpfr_set_str (x, str, base, rnd_mode);
                    199: }

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