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>