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 }