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