github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/demos/expr/exprfa.c (about)

     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  }