blob: bac1a9992e80b47a9ca5088fab8142568527d6a0 [file] [log] [blame]
Austin Schuhbb1338c2024-06-15 19:31:16 -07001/* mpz expression evaluation, simple part
2
3Copyright 2000-2002 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library.
6
7The GNU MP Library is free software; you can redistribute it and/or modify
8it 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
14or
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
20or both in parallel, as here.
21
22The GNU MP Library is distributed in the hope that it will be useful, but
23WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25for more details.
26
27You should have received copies of the GNU General Public License and the
28GNU Lesser General Public License along with the GNU MP Library. If not,
29see 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. */
43static int
44e_mpz_sgn (mpz_srcptr x)
45{
46 return mpz_sgn (x);
47}
48static int
49e_mpz_odd_p (mpz_srcptr x)
50{
51 return mpz_odd_p (x);
52}
53static int
54e_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". */
61static void
62e_mpz_hamdist (mpz_ptr w, mpz_srcptr x, mpz_srcptr y)
63{
64 mpz_set_ui (w, mpz_hamdist (x, y));
65}
66static void
67e_mpz_popcount (mpz_ptr w, mpz_srcptr x)
68{
69 mpz_set_ui (w, mpz_popcount (x));
70}
71static void
72e_mpz_scan0 (mpz_ptr w, mpz_srcptr x, unsigned long start)
73{
74 mpz_set_ui (w, mpz_scan0 (x, start));
75}
76static void
77e_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. */
85static void
86e_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}
92static void
93e_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
100static 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. */
186const struct mpexpr_operator_t * const mpz_expr_standard_table
187= _mpz_expr_standard_table;
188
189
190int
191mpz_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}