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