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

     1  /* mpz expression evaluation, simple part
     2  
     3  Copyright 2000-2002 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  #include <ctype.h>
    32  #include <stdio.h>
    33  #include <string.h>
    34  #include "gmp.h"
    35  #include "expr-impl.h"
    36  
    37  
    38  /* Change this to "#define TRACE(x) x" to get some traces. */
    39  #define TRACE(x)
    40  
    41  
    42  /* These are macros, so need function wrappers. */
    43  static int
    44  e_mpz_sgn (mpz_srcptr x)
    45  {
    46    return mpz_sgn (x);
    47  }
    48  static int
    49  e_mpz_odd_p (mpz_srcptr x)
    50  {
    51    return mpz_odd_p (x);
    52  }
    53  static int
    54  e_mpz_even_p (mpz_srcptr x)
    55  {
    56    return mpz_even_p (x);
    57  }
    58  
    59  /* These wrapped because MPEXPR_TYPE_I_ functions are expected to return
    60     "int" whereas these return "unsigned long".  */
    61  static void
    62  e_mpz_hamdist (mpz_ptr w, mpz_srcptr x, mpz_srcptr y)
    63  {
    64    mpz_set_ui (w, mpz_hamdist (x, y));
    65  }
    66  static void
    67  e_mpz_popcount (mpz_ptr w, mpz_srcptr x)
    68  {
    69    mpz_set_ui (w, mpz_popcount (x));
    70  }
    71  static void
    72  e_mpz_scan0 (mpz_ptr w, mpz_srcptr x, unsigned long start)
    73  {
    74    mpz_set_ui (w, mpz_scan0 (x, start));
    75  }
    76  static void
    77  e_mpz_scan1 (mpz_ptr w, mpz_srcptr x, unsigned long start)
    78  {
    79    mpz_set_ui (w, mpz_scan1 (x, start));
    80  }
    81  
    82  /* These wrapped because they're in-place whereas MPEXPR_TYPE_BINARY_UI
    83     expects a separate source and destination.  Actually the parser will
    84     normally pass w==x anyway.  */
    85  static void
    86  e_mpz_setbit (mpz_ptr w, mpz_srcptr x, unsigned long n)
    87  {
    88    if (w != x)
    89      mpz_set (w, x);
    90    mpz_setbit (w, n);
    91  }
    92  static void
    93  e_mpz_clrbit (mpz_ptr w, mpz_srcptr x, unsigned long n)
    94  {
    95    if (w != x)
    96      mpz_set (w, x);
    97    mpz_clrbit (w, n);
    98  }
    99  
   100  static const struct mpexpr_operator_t  _mpz_expr_standard_table[] = {
   101  
   102    { "**",  (mpexpr_fun_t) mpz_pow_ui,
   103      MPEXPR_TYPE_BINARY_UI | MPEXPR_TYPE_RIGHTASSOC,                  220 },
   104  
   105    { "~",   (mpexpr_fun_t) mpz_com,
   106      MPEXPR_TYPE_UNARY | MPEXPR_TYPE_PREFIX,                          210 },
   107    { "!",   (mpexpr_fun_t) e_mpz_sgn,
   108      MPEXPR_TYPE_LOGICAL_NOT | MPEXPR_TYPE_PREFIX,                    210 },
   109    { "-",   (mpexpr_fun_t) mpz_neg,
   110      MPEXPR_TYPE_UNARY | MPEXPR_TYPE_PREFIX,                          210 },
   111  
   112    { "*",   (mpexpr_fun_t) mpz_mul,          MPEXPR_TYPE_BINARY,      200 },
   113    { "/",   (mpexpr_fun_t) mpz_tdiv_q,       MPEXPR_TYPE_BINARY,      200 },
   114    { "%",   (mpexpr_fun_t) mpz_tdiv_r,       MPEXPR_TYPE_BINARY,      200 },
   115  
   116    { "+",   (mpexpr_fun_t) mpz_add,          MPEXPR_TYPE_BINARY,      190 },
   117    { "-",   (mpexpr_fun_t) mpz_sub,          MPEXPR_TYPE_BINARY,      190 },
   118  
   119    { "<<",  (mpexpr_fun_t) mpz_mul_2exp,     MPEXPR_TYPE_BINARY_UI,   180 },
   120    { ">>",  (mpexpr_fun_t) mpz_tdiv_q_2exp,  MPEXPR_TYPE_BINARY_UI,   180 },
   121  
   122    { "<=",  (mpexpr_fun_t) mpz_cmp,          MPEXPR_TYPE_CMP_LE,      170 },
   123    { "<",   (mpexpr_fun_t) mpz_cmp,          MPEXPR_TYPE_CMP_LT,      170 },
   124    { ">=",  (mpexpr_fun_t) mpz_cmp,          MPEXPR_TYPE_CMP_GE,      170 },
   125    { ">",   (mpexpr_fun_t) mpz_cmp,          MPEXPR_TYPE_CMP_GT,      170 },
   126  
   127    { "==",  (mpexpr_fun_t) mpz_cmp,          MPEXPR_TYPE_CMP_EQ,      160 },
   128    { "!=",  (mpexpr_fun_t) mpz_cmp,          MPEXPR_TYPE_CMP_NE,      160 },
   129  
   130    { "&",   (mpexpr_fun_t) mpz_and,          MPEXPR_TYPE_BINARY,      150 },
   131    { "^",   (mpexpr_fun_t) mpz_xor,          MPEXPR_TYPE_BINARY,      140 },
   132    { "|",   (mpexpr_fun_t) mpz_ior,          MPEXPR_TYPE_BINARY,      130 },
   133    { "&&",  (mpexpr_fun_t) e_mpz_sgn, MPEXPR_TYPE_LOGICAL_AND, 120 },
   134    { "||",  (mpexpr_fun_t) e_mpz_sgn, MPEXPR_TYPE_LOGICAL_OR,  110 },
   135  
   136    { ":",   NULL,                            MPEXPR_TYPE_COLON,       101 },
   137    { "?",   (mpexpr_fun_t) e_mpz_sgn, MPEXPR_TYPE_QUESTION,    100 },
   138  
   139    { ")",   NULL,                            MPEXPR_TYPE_CLOSEPAREN,   4 },
   140    { "(",   NULL,                            MPEXPR_TYPE_OPENPAREN,    3 },
   141    { ",",   NULL,                            MPEXPR_TYPE_ARGSEP,       2 },
   142    { "$",   NULL,                            MPEXPR_TYPE_VARIABLE,     1 },
   143  
   144    { "abs",       (mpexpr_fun_t) mpz_abs,           MPEXPR_TYPE_UNARY         },
   145    { "bin",       (mpexpr_fun_t) mpz_bin_ui,        MPEXPR_TYPE_BINARY_UI     },
   146    { "clrbit",    (mpexpr_fun_t) e_mpz_clrbit,      MPEXPR_TYPE_BINARY_UI     },
   147    { "cmp",       (mpexpr_fun_t) mpz_cmp,           MPEXPR_TYPE_I_BINARY      },
   148    { "cmpabs",    (mpexpr_fun_t) mpz_cmpabs,        MPEXPR_TYPE_I_BINARY      },
   149    { "congruent_p",(mpexpr_fun_t)mpz_congruent_p,   MPEXPR_TYPE_I_TERNARY     },
   150    { "divisible_p",(mpexpr_fun_t)mpz_divisible_p,   MPEXPR_TYPE_I_BINARY      },
   151    { "even_p",    (mpexpr_fun_t) e_mpz_even_p,      MPEXPR_TYPE_I_UNARY       },
   152    { "fib",       (mpexpr_fun_t) mpz_fib_ui,        MPEXPR_TYPE_UNARY_UI      },
   153    { "fac",       (mpexpr_fun_t) mpz_fac_ui,        MPEXPR_TYPE_UNARY_UI      },
   154    { "gcd",       (mpexpr_fun_t) mpz_gcd,           MPEXPR_TYPE_BINARY
   155  						   | MPEXPR_TYPE_PAIRWISE    },
   156    { "hamdist",   (mpexpr_fun_t) e_mpz_hamdist,     MPEXPR_TYPE_BINARY        },
   157    { "invert",    (mpexpr_fun_t) mpz_invert,        MPEXPR_TYPE_BINARY        },
   158    { "jacobi",    (mpexpr_fun_t) mpz_jacobi,        MPEXPR_TYPE_I_BINARY      },
   159    { "kronecker", (mpexpr_fun_t) mpz_kronecker,     MPEXPR_TYPE_I_BINARY      },
   160    { "lcm",       (mpexpr_fun_t) mpz_lcm,           MPEXPR_TYPE_BINARY
   161  						   | MPEXPR_TYPE_PAIRWISE    },
   162    { "lucnum",    (mpexpr_fun_t) mpz_lucnum_ui,     MPEXPR_TYPE_UNARY_UI      },
   163    { "max",       (mpexpr_fun_t) mpz_cmp,           MPEXPR_TYPE_MAX
   164  						   | MPEXPR_TYPE_PAIRWISE    },
   165    { "min",       (mpexpr_fun_t) mpz_cmp,           MPEXPR_TYPE_MIN
   166  						   | MPEXPR_TYPE_PAIRWISE    },
   167    { "nextprime", (mpexpr_fun_t) mpz_nextprime,     MPEXPR_TYPE_UNARY         },
   168    { "odd_p",     (mpexpr_fun_t) e_mpz_odd_p,       MPEXPR_TYPE_I_UNARY       },
   169    { "perfect_power_p", (mpexpr_fun_t)mpz_perfect_power_p, MPEXPR_TYPE_I_UNARY},
   170    { "perfect_square_p",(mpexpr_fun_t)mpz_perfect_square_p,MPEXPR_TYPE_I_UNARY},
   171    { "popcount",  (mpexpr_fun_t) e_mpz_popcount,    MPEXPR_TYPE_UNARY         },
   172    { "powm",      (mpexpr_fun_t) mpz_powm,          MPEXPR_TYPE_TERNARY       },
   173    { "probab_prime_p",  (mpexpr_fun_t)mpz_probab_prime_p,  MPEXPR_TYPE_I_UNARY},
   174    { "root",      (mpexpr_fun_t) mpz_root,          MPEXPR_TYPE_BINARY_UI     },
   175    { "scan0",     (mpexpr_fun_t) e_mpz_scan0,       MPEXPR_TYPE_BINARY_UI     },
   176    { "scan1",     (mpexpr_fun_t) e_mpz_scan1,       MPEXPR_TYPE_BINARY_UI     },
   177    { "setbit",    (mpexpr_fun_t) e_mpz_setbit,      MPEXPR_TYPE_BINARY_UI     },
   178    { "tstbit",    (mpexpr_fun_t) mpz_tstbit,        MPEXPR_TYPE_I_BINARY_UI   },
   179    { "sgn",       (mpexpr_fun_t) e_mpz_sgn,         MPEXPR_TYPE_I_UNARY       },
   180    { "sqrt",      (mpexpr_fun_t) mpz_sqrt,          MPEXPR_TYPE_UNARY         },
   181    { NULL }
   182  };
   183  
   184  /* The table is available globally only through a pointer, so the table size
   185     can change without breaking binary compatibility. */
   186  const struct mpexpr_operator_t * const mpz_expr_standard_table
   187  = _mpz_expr_standard_table;
   188  
   189  
   190  int
   191  mpz_expr (mpz_ptr res, int base, const char *e, ...)
   192  {
   193    mpz_srcptr  var[MPEXPR_VARIABLES];
   194    va_list     ap;
   195    int         ret;
   196    va_start (ap, e);
   197  
   198    TRACE (printf ("mpz_expr(): base %d, %s\n", base, e));
   199    ret = mpexpr_va_to_var ((void **) var, ap);
   200    va_end (ap);
   201  
   202    if (ret != MPEXPR_RESULT_OK)
   203      return ret;
   204  
   205    return mpz_expr_a (mpz_expr_standard_table, res, base, e, strlen(e), var);
   206  }