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
e_mpz_sgn(mpz_srcptr x)44 e_mpz_sgn (mpz_srcptr x)
45 {
46 return mpz_sgn (x);
47 }
48 static int
e_mpz_odd_p(mpz_srcptr x)49 e_mpz_odd_p (mpz_srcptr x)
50 {
51 return mpz_odd_p (x);
52 }
53 static int
e_mpz_even_p(mpz_srcptr x)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
e_mpz_hamdist(mpz_ptr w,mpz_srcptr x,mpz_srcptr y)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
e_mpz_popcount(mpz_ptr w,mpz_srcptr x)67 e_mpz_popcount (mpz_ptr w, mpz_srcptr x)
68 {
69 mpz_set_ui (w, mpz_popcount (x));
70 }
71 static void
e_mpz_scan0(mpz_ptr w,mpz_srcptr x,unsigned long start)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
e_mpz_scan1(mpz_ptr w,mpz_srcptr x,unsigned long start)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
e_mpz_setbit(mpz_ptr w,mpz_srcptr x,unsigned long n)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
e_mpz_clrbit(mpz_ptr w,mpz_srcptr x,unsigned long n)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
mpz_expr(mpz_ptr res,int base,const char * e,...)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 }
207