(root)/
gmp-6.3.0/
demos/
expr/
exprz.c
       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  }