exprfa.c revision 1.1 1 1.1 mrg /* mpf expression evaluation
2 1.1 mrg
3 1.1 mrg Copyright 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
4 1.1 mrg
5 1.1 mrg This file is part of the GNU MP Library.
6 1.1 mrg
7 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
8 1.1 mrg it under the terms of the GNU Lesser General Public License as published by
9 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
10 1.1 mrg option) any later version.
11 1.1 mrg
12 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
13 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 1.1 mrg License for more details.
16 1.1 mrg
17 1.1 mrg You should have received a copy of the GNU Lesser General Public License
18 1.1 mrg along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
19 1.1 mrg
20 1.1 mrg
21 1.1 mrg /* Future: Bitwise "&", "|" and "&" could be done, if desired. Not sure
22 1.1 mrg those functions would be much value though. */
23 1.1 mrg
24 1.1 mrg
25 1.1 mrg #include <ctype.h>
26 1.1 mrg #include <stdio.h>
27 1.1 mrg #include <string.h>
28 1.1 mrg
29 1.1 mrg #include "gmp.h"
30 1.1 mrg #include "expr-impl.h"
31 1.1 mrg
32 1.1 mrg
33 1.1 mrg /* Change this to "#define TRACE(x) x" to get some traces. */
34 1.1 mrg #define TRACE(x)
35 1.1 mrg
36 1.1 mrg
37 1.1 mrg static size_t
38 1.1 mrg e_mpf_number (mpf_ptr res, __gmp_const char *e, size_t elen, int base)
39 1.1 mrg {
40 1.1 mrg char *edup;
41 1.1 mrg size_t i, ret, extra=0;
42 1.1 mrg int mant_base, exp_base;
43 1.1 mrg void *(*allocate_func) (size_t);
44 1.1 mrg void (*free_func) (void *, size_t);
45 1.1 mrg
46 1.1 mrg TRACE (printf ("mpf_number base=%d \"%.*s\"\n", base, (int) elen, e));
47 1.1 mrg
48 1.1 mrg /* mpf_set_str doesn't currently accept 0x for hex in base==0, so do it
49 1.1 mrg here instead. FIXME: Would prefer to let mpf_set_str handle this. */
50 1.1 mrg if (base == 0 && elen >= 2 && e[0] == '0' && (e[1] == 'x' || e[1] == 'X'))
51 1.1 mrg {
52 1.1 mrg base = 16;
53 1.1 mrg extra = 2;
54 1.1 mrg e += extra;
55 1.1 mrg elen -= extra;
56 1.1 mrg }
57 1.1 mrg
58 1.1 mrg if (base == 0)
59 1.1 mrg mant_base = 10;
60 1.1 mrg else if (base < 0)
61 1.1 mrg mant_base = -base;
62 1.1 mrg else
63 1.1 mrg mant_base = base;
64 1.1 mrg
65 1.1 mrg /* exponent in decimal if base is negative */
66 1.1 mrg if (base < 0)
67 1.1 mrg exp_base = 10;
68 1.1 mrg else if (base == 0)
69 1.1 mrg exp_base = 10;
70 1.1 mrg else
71 1.1 mrg exp_base = base;
72 1.1 mrg
73 1.1 mrg #define IS_EXPONENT(c) \
74 1.1 mrg (c == '@' || (base <= 10 && base >= -10 && (e[i] == 'e' || e[i] == 'E')))
75 1.1 mrg
76 1.1 mrg i = 0;
77 1.1 mrg for (;;)
78 1.1 mrg {
79 1.1 mrg if (i >= elen)
80 1.1 mrg goto parsed;
81 1.1 mrg if (e[i] == '.')
82 1.1 mrg break;
83 1.1 mrg if (IS_EXPONENT (e[i]))
84 1.1 mrg goto exponent;
85 1.1 mrg if (! isasciidigit_in_base (e[i], mant_base))
86 1.1 mrg goto parsed;
87 1.1 mrg i++;
88 1.1 mrg }
89 1.1 mrg
90 1.1 mrg /* fraction */
91 1.1 mrg i++;
92 1.1 mrg for (;;)
93 1.1 mrg {
94 1.1 mrg if (i >= elen)
95 1.1 mrg goto parsed;
96 1.1 mrg if (IS_EXPONENT (e[i]))
97 1.1 mrg goto exponent;
98 1.1 mrg if (! isasciidigit_in_base (e[i], mant_base))
99 1.1 mrg goto parsed;
100 1.1 mrg i++;
101 1.1 mrg }
102 1.1 mrg
103 1.1 mrg exponent:
104 1.1 mrg i++;
105 1.1 mrg if (i >= elen)
106 1.1 mrg goto parsed;
107 1.1 mrg if (e[i] == '-')
108 1.1 mrg i++;
109 1.1 mrg for (;;)
110 1.1 mrg {
111 1.1 mrg if (i >= elen)
112 1.1 mrg goto parsed;
113 1.1 mrg if (! isasciidigit_in_base (e[i], exp_base))
114 1.1 mrg break;
115 1.1 mrg i++;
116 1.1 mrg }
117 1.1 mrg
118 1.1 mrg parsed:
119 1.1 mrg TRACE (printf (" parsed i=%u \"%.*s\"\n", i, (int) i, e));
120 1.1 mrg
121 1.1 mrg mp_get_memory_functions (&allocate_func, NULL, &free_func);
122 1.1 mrg edup = (*allocate_func) (i+1);
123 1.1 mrg memcpy (edup, e, i);
124 1.1 mrg edup[i] = '\0';
125 1.1 mrg
126 1.1 mrg if (mpf_set_str (res, edup, base) == 0)
127 1.1 mrg ret = i + extra;
128 1.1 mrg else
129 1.1 mrg ret = 0;
130 1.1 mrg
131 1.1 mrg (*free_func) (edup, i+1);
132 1.1 mrg return ret;
133 1.1 mrg }
134 1.1 mrg
135 1.1 mrg static int
136 1.1 mrg e_mpf_ulong_p (mpf_srcptr f)
137 1.1 mrg {
138 1.1 mrg return mpf_integer_p (f) && mpf_fits_ulong_p (f);
139 1.1 mrg }
140 1.1 mrg
141 1.1 mrg /* Don't want to change the precision of w, can only do an actual swap when
142 1.1 mrg w and x have the same precision. */
143 1.1 mrg static void
144 1.1 mrg e_mpf_set_or_swap (mpf_ptr w, mpf_ptr x)
145 1.1 mrg {
146 1.1 mrg if (mpf_get_prec (w) == mpf_get_prec (x))
147 1.1 mrg mpf_swap (w, x);
148 1.1 mrg else
149 1.1 mrg mpf_set (w, x);
150 1.1 mrg }
151 1.1 mrg
152 1.1 mrg
153 1.1 mrg int
154 1.1 mrg mpf_expr_a (__gmp_const struct mpexpr_operator_t *table,
155 1.1 mrg mpf_ptr res, int base, unsigned long prec,
156 1.1 mrg __gmp_const char *e, size_t elen,
157 1.1 mrg mpf_srcptr var[26])
158 1.1 mrg {
159 1.1 mrg struct mpexpr_parse_t p;
160 1.1 mrg
161 1.1 mrg p.table = table;
162 1.1 mrg p.res = (mpX_ptr) res;
163 1.1 mrg p.base = base;
164 1.1 mrg p.prec = prec;
165 1.1 mrg p.e = e;
166 1.1 mrg p.elen = elen;
167 1.1 mrg p.var = (mpX_srcptr *) var;
168 1.1 mrg
169 1.1 mrg p.mpX_clear = (mpexpr_fun_one_t) mpf_clear;
170 1.1 mrg p.mpX_ulong_p = (mpexpr_fun_i_unary_t) e_mpf_ulong_p;
171 1.1 mrg p.mpX_get_ui = (mpexpr_fun_get_ui_t) mpf_get_ui;
172 1.1 mrg p.mpX_init = (mpexpr_fun_unary_ui_t) mpf_init2;
173 1.1 mrg p.mpX_number = (mpexpr_fun_number_t) e_mpf_number;
174 1.1 mrg p.mpX_set = (mpexpr_fun_unary_t) mpf_set;
175 1.1 mrg p.mpX_set_or_swap = (mpexpr_fun_unary_t) e_mpf_set_or_swap;
176 1.1 mrg p.mpX_set_si = (mpexpr_fun_set_si_t) mpf_set_si;
177 1.1 mrg p.mpX_swap = (mpexpr_fun_swap_t) mpf_swap;
178 1.1 mrg
179 1.1 mrg return mpexpr_evaluate (&p);
180 1.1 mrg }
181