Annotation of OpenXM_contrib/gmp/mpfr/set_str.c, Revision 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>