xref: /netbsd-src/external/lgpl3/gmp/dist/demos/expr/exprz.c (revision ce54336801cf28877c3414aa2fcb251dddd543a2)
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