1 1.1 mrg /* Program for computing integer expressions using the GNU Multiple Precision 2 1.1 mrg Arithmetic Library. 3 1.1 mrg 4 1.1.1.3 mrg Copyright 1997, 1999-2002, 2005, 2008, 2012, 2015 Free Software Foundation, Inc. 5 1.1 mrg 6 1.1 mrg This program is free software; you can redistribute it and/or modify it under 7 1.1 mrg the terms of the GNU General Public License as published by the Free Software 8 1.1 mrg Foundation; either version 3 of the License, or (at your option) any later 9 1.1 mrg version. 10 1.1 mrg 11 1.1 mrg This program is distributed in the hope that it will be useful, but WITHOUT ANY 12 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 1.1 mrg PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 1.1 mrg 15 1.1 mrg You should have received a copy of the GNU General Public License along with 16 1.1.1.3 mrg this program. If not, see https://www.gnu.org/licenses/. */ 17 1.1 mrg 18 1.1 mrg 19 1.1 mrg /* This expressions evaluator works by building an expression tree (using a 20 1.1 mrg recursive descent parser) which is then evaluated. The expression tree is 21 1.1 mrg useful since we want to optimize certain expressions (like a^b % c). 22 1.1 mrg 23 1.1 mrg Usage: pexpr [options] expr ... 24 1.1 mrg (Assuming you called the executable `pexpr' of course.) 25 1.1 mrg 26 1.1 mrg Command line options: 27 1.1 mrg 28 1.1 mrg -b print output in binary 29 1.1 mrg -o print output in octal 30 1.1 mrg -d print output in decimal (the default) 31 1.1 mrg -x print output in hexadecimal 32 1.1 mrg -b<NUM> print output in base NUM 33 1.1 mrg -t print timing information 34 1.1 mrg -html output html 35 1.1 mrg -wml output wml 36 1.1 mrg -split split long lines each 80th digit 37 1.1 mrg */ 38 1.1 mrg 39 1.1 mrg /* Define LIMIT_RESOURCE_USAGE if you want to make sure the program doesn't 40 1.1 mrg use up extensive resources (cpu, memory). Useful for the GMP demo on the 41 1.1 mrg GMP web site, since we cannot load the server too much. */ 42 1.1 mrg 43 1.1 mrg #include "pexpr-config.h" 44 1.1 mrg 45 1.1 mrg #include <string.h> 46 1.1 mrg #include <stdio.h> 47 1.1 mrg #include <stdlib.h> 48 1.1 mrg #include <setjmp.h> 49 1.1 mrg #include <signal.h> 50 1.1 mrg #include <ctype.h> 51 1.1 mrg 52 1.1 mrg #include <time.h> 53 1.1 mrg #include <sys/types.h> 54 1.1 mrg #include <sys/time.h> 55 1.1 mrg #if HAVE_SYS_RESOURCE_H 56 1.1 mrg #include <sys/resource.h> 57 1.1 mrg #endif 58 1.1 mrg 59 1.1 mrg #include "gmp.h" 60 1.1 mrg 61 1.1 mrg /* SunOS 4 and HPUX 9 don't define a canonical SIGSTKSZ, use a default. */ 62 1.1 mrg #ifndef SIGSTKSZ 63 1.1 mrg #define SIGSTKSZ 4096 64 1.1 mrg #endif 65 1.1 mrg 66 1.1 mrg 67 1.1 mrg #define TIME(t,func) \ 68 1.1 mrg do { int __t0, __tmp; \ 69 1.1 mrg __t0 = cputime (); \ 70 1.1 mrg {func;} \ 71 1.1 mrg __tmp = cputime () - __t0; \ 72 1.1 mrg (t) = __tmp; \ 73 1.1 mrg } while (0) 74 1.1 mrg 75 1.1 mrg /* GMP version 1.x compatibility. */ 76 1.1 mrg #if ! (__GNU_MP_VERSION >= 2) 77 1.1 mrg typedef MP_INT __mpz_struct; 78 1.1 mrg typedef __mpz_struct mpz_t[1]; 79 1.1 mrg typedef __mpz_struct *mpz_ptr; 80 1.1 mrg #define mpz_fdiv_q mpz_div 81 1.1 mrg #define mpz_fdiv_r mpz_mod 82 1.1 mrg #define mpz_tdiv_q_2exp mpz_div_2exp 83 1.1 mrg #define mpz_sgn(Z) ((Z)->size < 0 ? -1 : (Z)->size > 0) 84 1.1 mrg #endif 85 1.1 mrg 86 1.1 mrg /* GMP version 2.0 compatibility. */ 87 1.1 mrg #if ! (__GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1) 88 1.1 mrg #define mpz_swap(a,b) \ 89 1.1 mrg do { __mpz_struct __t; __t = *a; *a = *b; *b = __t;} while (0) 90 1.1 mrg #endif 91 1.1 mrg 92 1.1 mrg jmp_buf errjmpbuf; 93 1.1 mrg 94 1.1 mrg enum op_t {NOP, LIT, NEG, NOT, PLUS, MINUS, MULT, DIV, MOD, REM, INVMOD, POW, 95 1.1 mrg AND, IOR, XOR, SLL, SRA, POPCNT, HAMDIST, GCD, LCM, SQRT, ROOT, FAC, 96 1.1 mrg LOG, LOG2, FERMAT, MERSENNE, FIBONACCI, RANDOM, NEXTPRIME, BINOM, 97 1.1 mrg TIMING}; 98 1.1 mrg 99 1.1 mrg /* Type for the expression tree. */ 100 1.1 mrg struct expr 101 1.1 mrg { 102 1.1 mrg enum op_t op; 103 1.1 mrg union 104 1.1 mrg { 105 1.1 mrg struct {struct expr *lhs, *rhs;} ops; 106 1.1 mrg mpz_t val; 107 1.1 mrg } operands; 108 1.1 mrg }; 109 1.1 mrg 110 1.1 mrg typedef struct expr *expr_t; 111 1.1 mrg 112 1.1.1.2 mrg void cleanup_and_exit (int); 113 1.1 mrg 114 1.1.1.2 mrg char *skipspace (char *); 115 1.1.1.2 mrg void makeexp (expr_t *, enum op_t, expr_t, expr_t); 116 1.1.1.2 mrg void free_expr (expr_t); 117 1.1.1.2 mrg char *expr (char *, expr_t *); 118 1.1.1.2 mrg char *term (char *, expr_t *); 119 1.1.1.2 mrg char *power (char *, expr_t *); 120 1.1.1.2 mrg char *factor (char *, expr_t *); 121 1.1.1.2 mrg int match (char *, char *); 122 1.1.1.2 mrg int matchp (char *, char *); 123 1.1.1.2 mrg int cputime (void); 124 1.1 mrg 125 1.1.1.2 mrg void mpz_eval_expr (mpz_ptr, expr_t); 126 1.1.1.2 mrg void mpz_eval_mod_expr (mpz_ptr, expr_t, mpz_ptr); 127 1.1 mrg 128 1.1 mrg char *error; 129 1.1 mrg int flag_print = 1; 130 1.1 mrg int print_timing = 0; 131 1.1 mrg int flag_html = 0; 132 1.1 mrg int flag_wml = 0; 133 1.1 mrg int flag_splitup_output = 0; 134 1.1 mrg char *newline = ""; 135 1.1 mrg gmp_randstate_t rstate; 136 1.1 mrg 137 1.1 mrg 138 1.1 mrg 139 1.1 mrg /* cputime() returns user CPU time measured in milliseconds. */ 140 1.1 mrg #if ! HAVE_CPUTIME 141 1.1 mrg #if HAVE_GETRUSAGE 142 1.1 mrg int 143 1.1 mrg cputime (void) 144 1.1 mrg { 145 1.1 mrg struct rusage rus; 146 1.1 mrg 147 1.1 mrg getrusage (0, &rus); 148 1.1 mrg return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; 149 1.1 mrg } 150 1.1 mrg #else 151 1.1 mrg #if HAVE_CLOCK 152 1.1 mrg int 153 1.1 mrg cputime (void) 154 1.1 mrg { 155 1.1 mrg if (CLOCKS_PER_SEC < 100000) 156 1.1 mrg return clock () * 1000 / CLOCKS_PER_SEC; 157 1.1 mrg return clock () / (CLOCKS_PER_SEC / 1000); 158 1.1 mrg } 159 1.1 mrg #else 160 1.1 mrg int 161 1.1 mrg cputime (void) 162 1.1 mrg { 163 1.1 mrg return 0; 164 1.1 mrg } 165 1.1 mrg #endif 166 1.1 mrg #endif 167 1.1 mrg #endif 168 1.1 mrg 169 1.1 mrg 170 1.1 mrg int 171 1.1 mrg stack_downwards_helper (char *xp) 172 1.1 mrg { 173 1.1 mrg char y; 174 1.1 mrg return &y < xp; 175 1.1 mrg } 176 1.1 mrg int 177 1.1 mrg stack_downwards_p (void) 178 1.1 mrg { 179 1.1 mrg char x; 180 1.1 mrg return stack_downwards_helper (&x); 181 1.1 mrg } 182 1.1 mrg 183 1.1 mrg 184 1.1 mrg void 185 1.1 mrg setup_error_handler (void) 186 1.1 mrg { 187 1.1 mrg #if HAVE_SIGACTION 188 1.1 mrg struct sigaction act; 189 1.1 mrg act.sa_handler = cleanup_and_exit; 190 1.1 mrg sigemptyset (&(act.sa_mask)); 191 1.1 mrg #define SIGNAL(sig) sigaction (sig, &act, NULL) 192 1.1 mrg #else 193 1.1 mrg struct { int sa_flags; } act; 194 1.1 mrg #define SIGNAL(sig) signal (sig, cleanup_and_exit) 195 1.1 mrg #endif 196 1.1 mrg act.sa_flags = 0; 197 1.1 mrg 198 1.1 mrg /* Set up a stack for signal handling. A typical cause of error is stack 199 1.1 mrg overflow, and in such situation a signal can not be delivered on the 200 1.1 mrg overflown stack. */ 201 1.1 mrg #if HAVE_SIGALTSTACK 202 1.1 mrg { 203 1.1 mrg /* AIX uses stack_t, MacOS uses struct sigaltstack, various other 204 1.1 mrg systems have both. */ 205 1.1 mrg #if HAVE_STACK_T 206 1.1 mrg stack_t s; 207 1.1 mrg #else 208 1.1 mrg struct sigaltstack s; 209 1.1 mrg #endif 210 1.1 mrg s.ss_sp = malloc (SIGSTKSZ); 211 1.1 mrg s.ss_size = SIGSTKSZ; 212 1.1 mrg s.ss_flags = 0; 213 1.1 mrg if (sigaltstack (&s, NULL) != 0) 214 1.1 mrg perror("sigaltstack"); 215 1.1 mrg act.sa_flags = SA_ONSTACK; 216 1.1 mrg } 217 1.1 mrg #else 218 1.1 mrg #if HAVE_SIGSTACK 219 1.1 mrg { 220 1.1 mrg struct sigstack s; 221 1.1 mrg s.ss_sp = malloc (SIGSTKSZ); 222 1.1 mrg if (stack_downwards_p ()) 223 1.1 mrg s.ss_sp += SIGSTKSZ; 224 1.1 mrg s.ss_onstack = 0; 225 1.1 mrg if (sigstack (&s, NULL) != 0) 226 1.1 mrg perror("sigstack"); 227 1.1 mrg act.sa_flags = SA_ONSTACK; 228 1.1 mrg } 229 1.1 mrg #else 230 1.1 mrg #endif 231 1.1 mrg #endif 232 1.1 mrg 233 1.1 mrg #ifdef LIMIT_RESOURCE_USAGE 234 1.1 mrg { 235 1.1 mrg struct rlimit limit; 236 1.1 mrg 237 1.1 mrg limit.rlim_cur = limit.rlim_max = 0; 238 1.1 mrg setrlimit (RLIMIT_CORE, &limit); 239 1.1 mrg 240 1.1 mrg limit.rlim_cur = 3; 241 1.1 mrg limit.rlim_max = 4; 242 1.1 mrg setrlimit (RLIMIT_CPU, &limit); 243 1.1 mrg 244 1.1 mrg limit.rlim_cur = limit.rlim_max = 16 * 1024 * 1024; 245 1.1 mrg setrlimit (RLIMIT_DATA, &limit); 246 1.1 mrg 247 1.1 mrg getrlimit (RLIMIT_STACK, &limit); 248 1.1 mrg limit.rlim_cur = 4 * 1024 * 1024; 249 1.1 mrg setrlimit (RLIMIT_STACK, &limit); 250 1.1 mrg 251 1.1 mrg SIGNAL (SIGXCPU); 252 1.1 mrg } 253 1.1 mrg #endif /* LIMIT_RESOURCE_USAGE */ 254 1.1 mrg 255 1.1 mrg SIGNAL (SIGILL); 256 1.1 mrg SIGNAL (SIGSEGV); 257 1.1 mrg #ifdef SIGBUS /* not in mingw */ 258 1.1 mrg SIGNAL (SIGBUS); 259 1.1 mrg #endif 260 1.1 mrg SIGNAL (SIGFPE); 261 1.1 mrg SIGNAL (SIGABRT); 262 1.1 mrg } 263 1.1 mrg 264 1.1 mrg int 265 1.1 mrg main (int argc, char **argv) 266 1.1 mrg { 267 1.1 mrg struct expr *e; 268 1.1 mrg int i; 269 1.1 mrg mpz_t r; 270 1.1 mrg int errcode = 0; 271 1.1 mrg char *str; 272 1.1 mrg int base = 10; 273 1.1 mrg 274 1.1 mrg setup_error_handler (); 275 1.1 mrg 276 1.1 mrg gmp_randinit (rstate, GMP_RAND_ALG_LC, 128); 277 1.1 mrg 278 1.1 mrg { 279 1.1 mrg #if HAVE_GETTIMEOFDAY 280 1.1 mrg struct timeval tv; 281 1.1 mrg gettimeofday (&tv, NULL); 282 1.1 mrg gmp_randseed_ui (rstate, tv.tv_sec + tv.tv_usec); 283 1.1 mrg #else 284 1.1 mrg time_t t; 285 1.1 mrg time (&t); 286 1.1 mrg gmp_randseed_ui (rstate, t); 287 1.1 mrg #endif 288 1.1 mrg } 289 1.1 mrg 290 1.1 mrg mpz_init (r); 291 1.1 mrg 292 1.1 mrg while (argc > 1 && argv[1][0] == '-') 293 1.1 mrg { 294 1.1 mrg char *arg = argv[1]; 295 1.1 mrg 296 1.1 mrg if (arg[1] >= '0' && arg[1] <= '9') 297 1.1 mrg break; 298 1.1 mrg 299 1.1 mrg if (arg[1] == 't') 300 1.1 mrg print_timing = 1; 301 1.1 mrg else if (arg[1] == 'b' && arg[2] >= '0' && arg[2] <= '9') 302 1.1 mrg { 303 1.1 mrg base = atoi (arg + 2); 304 1.1 mrg if (base < 2 || base > 62) 305 1.1 mrg { 306 1.1 mrg fprintf (stderr, "error: invalid output base\n"); 307 1.1 mrg exit (-1); 308 1.1 mrg } 309 1.1 mrg } 310 1.1 mrg else if (arg[1] == 'b' && arg[2] == 0) 311 1.1 mrg base = 2; 312 1.1 mrg else if (arg[1] == 'x' && arg[2] == 0) 313 1.1 mrg base = 16; 314 1.1 mrg else if (arg[1] == 'X' && arg[2] == 0) 315 1.1 mrg base = -16; 316 1.1 mrg else if (arg[1] == 'o' && arg[2] == 0) 317 1.1 mrg base = 8; 318 1.1 mrg else if (arg[1] == 'd' && arg[2] == 0) 319 1.1 mrg base = 10; 320 1.1 mrg else if (arg[1] == 'v' && arg[2] == 0) 321 1.1 mrg { 322 1.1 mrg printf ("pexpr linked to gmp %s\n", __gmp_version); 323 1.1 mrg } 324 1.1 mrg else if (strcmp (arg, "-html") == 0) 325 1.1 mrg { 326 1.1 mrg flag_html = 1; 327 1.1 mrg newline = "<br>"; 328 1.1 mrg } 329 1.1 mrg else if (strcmp (arg, "-wml") == 0) 330 1.1 mrg { 331 1.1 mrg flag_wml = 1; 332 1.1 mrg newline = "<br/>"; 333 1.1 mrg } 334 1.1 mrg else if (strcmp (arg, "-split") == 0) 335 1.1 mrg { 336 1.1 mrg flag_splitup_output = 1; 337 1.1 mrg } 338 1.1 mrg else if (strcmp (arg, "-noprint") == 0) 339 1.1 mrg { 340 1.1 mrg flag_print = 0; 341 1.1 mrg } 342 1.1 mrg else 343 1.1 mrg { 344 1.1 mrg fprintf (stderr, "error: unknown option `%s'\n", arg); 345 1.1 mrg exit (-1); 346 1.1 mrg } 347 1.1 mrg argv++; 348 1.1 mrg argc--; 349 1.1 mrg } 350 1.1 mrg 351 1.1 mrg for (i = 1; i < argc; i++) 352 1.1 mrg { 353 1.1 mrg int s; 354 1.1 mrg int jmpval; 355 1.1 mrg 356 1.1 mrg /* Set up error handler for parsing expression. */ 357 1.1 mrg jmpval = setjmp (errjmpbuf); 358 1.1 mrg if (jmpval != 0) 359 1.1 mrg { 360 1.1 mrg fprintf (stderr, "error: %s%s\n", error, newline); 361 1.1 mrg fprintf (stderr, " %s%s\n", argv[i], newline); 362 1.1 mrg if (! flag_html) 363 1.1 mrg { 364 1.1 mrg /* ??? Dunno how to align expression position with arrow in 365 1.1 mrg HTML ??? */ 366 1.1 mrg fprintf (stderr, " "); 367 1.1 mrg for (s = jmpval - (long) argv[i]; --s >= 0; ) 368 1.1 mrg putc (' ', stderr); 369 1.1 mrg fprintf (stderr, "^\n"); 370 1.1 mrg } 371 1.1 mrg 372 1.1 mrg errcode |= 1; 373 1.1 mrg continue; 374 1.1 mrg } 375 1.1 mrg 376 1.1 mrg str = expr (argv[i], &e); 377 1.1 mrg 378 1.1 mrg if (str[0] != 0) 379 1.1 mrg { 380 1.1 mrg fprintf (stderr, 381 1.1 mrg "error: garbage where end of expression expected%s\n", 382 1.1 mrg newline); 383 1.1 mrg fprintf (stderr, " %s%s\n", argv[i], newline); 384 1.1 mrg if (! flag_html) 385 1.1 mrg { 386 1.1 mrg /* ??? Dunno how to align expression position with arrow in 387 1.1 mrg HTML ??? */ 388 1.1 mrg fprintf (stderr, " "); 389 1.1 mrg for (s = str - argv[i]; --s; ) 390 1.1 mrg putc (' ', stderr); 391 1.1 mrg fprintf (stderr, "^\n"); 392 1.1 mrg } 393 1.1 mrg 394 1.1 mrg errcode |= 1; 395 1.1 mrg free_expr (e); 396 1.1 mrg continue; 397 1.1 mrg } 398 1.1 mrg 399 1.1 mrg /* Set up error handler for evaluating expression. */ 400 1.1 mrg if (setjmp (errjmpbuf)) 401 1.1 mrg { 402 1.1 mrg fprintf (stderr, "error: %s%s\n", error, newline); 403 1.1 mrg fprintf (stderr, " %s%s\n", argv[i], newline); 404 1.1 mrg if (! flag_html) 405 1.1 mrg { 406 1.1 mrg /* ??? Dunno how to align expression position with arrow in 407 1.1 mrg HTML ??? */ 408 1.1 mrg fprintf (stderr, " "); 409 1.1 mrg for (s = str - argv[i]; --s >= 0; ) 410 1.1 mrg putc (' ', stderr); 411 1.1 mrg fprintf (stderr, "^\n"); 412 1.1 mrg } 413 1.1 mrg 414 1.1 mrg errcode |= 2; 415 1.1 mrg continue; 416 1.1 mrg } 417 1.1 mrg 418 1.1 mrg if (print_timing) 419 1.1 mrg { 420 1.1 mrg int t; 421 1.1 mrg TIME (t, mpz_eval_expr (r, e)); 422 1.1 mrg printf ("computation took %d ms%s\n", t, newline); 423 1.1 mrg } 424 1.1 mrg else 425 1.1 mrg mpz_eval_expr (r, e); 426 1.1 mrg 427 1.1 mrg if (flag_print) 428 1.1 mrg { 429 1.1 mrg size_t out_len; 430 1.1 mrg char *tmp, *s; 431 1.1 mrg 432 1.1 mrg out_len = mpz_sizeinbase (r, base >= 0 ? base : -base) + 2; 433 1.1 mrg #ifdef LIMIT_RESOURCE_USAGE 434 1.1 mrg if (out_len > 100000) 435 1.1 mrg { 436 1.1 mrg printf ("result is about %ld digits, not printing it%s\n", 437 1.1 mrg (long) out_len - 3, newline); 438 1.1 mrg exit (-2); 439 1.1 mrg } 440 1.1 mrg #endif 441 1.1 mrg tmp = malloc (out_len); 442 1.1 mrg 443 1.1 mrg if (print_timing) 444 1.1 mrg { 445 1.1 mrg int t; 446 1.1 mrg printf ("output conversion "); 447 1.1 mrg TIME (t, mpz_get_str (tmp, base, r)); 448 1.1 mrg printf ("took %d ms%s\n", t, newline); 449 1.1 mrg } 450 1.1 mrg else 451 1.1 mrg mpz_get_str (tmp, base, r); 452 1.1 mrg 453 1.1 mrg out_len = strlen (tmp); 454 1.1 mrg if (flag_splitup_output) 455 1.1 mrg { 456 1.1 mrg for (s = tmp; out_len > 80; s += 80) 457 1.1 mrg { 458 1.1 mrg fwrite (s, 1, 80, stdout); 459 1.1 mrg printf ("%s\n", newline); 460 1.1 mrg out_len -= 80; 461 1.1 mrg } 462 1.1 mrg 463 1.1 mrg fwrite (s, 1, out_len, stdout); 464 1.1 mrg } 465 1.1 mrg else 466 1.1 mrg { 467 1.1 mrg fwrite (tmp, 1, out_len, stdout); 468 1.1 mrg } 469 1.1 mrg 470 1.1 mrg free (tmp); 471 1.1 mrg printf ("%s\n", newline); 472 1.1 mrg } 473 1.1 mrg else 474 1.1 mrg { 475 1.1 mrg printf ("result is approximately %ld digits%s\n", 476 1.1 mrg (long) mpz_sizeinbase (r, base >= 0 ? base : -base), 477 1.1 mrg newline); 478 1.1 mrg } 479 1.1 mrg 480 1.1 mrg free_expr (e); 481 1.1 mrg } 482 1.1 mrg 483 1.1.1.3 mrg mpz_clear (r); 484 1.1.1.3 mrg 485 1.1 mrg exit (errcode); 486 1.1 mrg } 487 1.1 mrg 488 1.1 mrg char * 489 1.1 mrg expr (char *str, expr_t *e) 490 1.1 mrg { 491 1.1 mrg expr_t e2; 492 1.1 mrg 493 1.1 mrg str = skipspace (str); 494 1.1 mrg if (str[0] == '+') 495 1.1 mrg { 496 1.1 mrg str = term (str + 1, e); 497 1.1 mrg } 498 1.1 mrg else if (str[0] == '-') 499 1.1 mrg { 500 1.1 mrg str = term (str + 1, e); 501 1.1 mrg makeexp (e, NEG, *e, NULL); 502 1.1 mrg } 503 1.1 mrg else if (str[0] == '~') 504 1.1 mrg { 505 1.1 mrg str = term (str + 1, e); 506 1.1 mrg makeexp (e, NOT, *e, NULL); 507 1.1 mrg } 508 1.1 mrg else 509 1.1 mrg { 510 1.1 mrg str = term (str, e); 511 1.1 mrg } 512 1.1 mrg 513 1.1 mrg for (;;) 514 1.1 mrg { 515 1.1 mrg str = skipspace (str); 516 1.1 mrg switch (str[0]) 517 1.1 mrg { 518 1.1 mrg case 'p': 519 1.1 mrg if (match ("plus", str)) 520 1.1 mrg { 521 1.1 mrg str = term (str + 4, &e2); 522 1.1 mrg makeexp (e, PLUS, *e, e2); 523 1.1 mrg } 524 1.1 mrg else 525 1.1 mrg return str; 526 1.1 mrg break; 527 1.1 mrg case 'm': 528 1.1 mrg if (match ("minus", str)) 529 1.1 mrg { 530 1.1 mrg str = term (str + 5, &e2); 531 1.1 mrg makeexp (e, MINUS, *e, e2); 532 1.1 mrg } 533 1.1 mrg else 534 1.1 mrg return str; 535 1.1 mrg break; 536 1.1 mrg case '+': 537 1.1 mrg str = term (str + 1, &e2); 538 1.1 mrg makeexp (e, PLUS, *e, e2); 539 1.1 mrg break; 540 1.1 mrg case '-': 541 1.1 mrg str = term (str + 1, &e2); 542 1.1 mrg makeexp (e, MINUS, *e, e2); 543 1.1 mrg break; 544 1.1 mrg default: 545 1.1 mrg return str; 546 1.1 mrg } 547 1.1 mrg } 548 1.1 mrg } 549 1.1 mrg 550 1.1 mrg char * 551 1.1 mrg term (char *str, expr_t *e) 552 1.1 mrg { 553 1.1 mrg expr_t e2; 554 1.1 mrg 555 1.1 mrg str = power (str, e); 556 1.1 mrg for (;;) 557 1.1 mrg { 558 1.1 mrg str = skipspace (str); 559 1.1 mrg switch (str[0]) 560 1.1 mrg { 561 1.1 mrg case 'm': 562 1.1 mrg if (match ("mul", str)) 563 1.1 mrg { 564 1.1 mrg str = power (str + 3, &e2); 565 1.1 mrg makeexp (e, MULT, *e, e2); 566 1.1 mrg break; 567 1.1 mrg } 568 1.1 mrg if (match ("mod", str)) 569 1.1 mrg { 570 1.1 mrg str = power (str + 3, &e2); 571 1.1 mrg makeexp (e, MOD, *e, e2); 572 1.1 mrg break; 573 1.1 mrg } 574 1.1 mrg return str; 575 1.1 mrg case 'd': 576 1.1 mrg if (match ("div", str)) 577 1.1 mrg { 578 1.1 mrg str = power (str + 3, &e2); 579 1.1 mrg makeexp (e, DIV, *e, e2); 580 1.1 mrg break; 581 1.1 mrg } 582 1.1 mrg return str; 583 1.1 mrg case 'r': 584 1.1 mrg if (match ("rem", str)) 585 1.1 mrg { 586 1.1 mrg str = power (str + 3, &e2); 587 1.1 mrg makeexp (e, REM, *e, e2); 588 1.1 mrg break; 589 1.1 mrg } 590 1.1 mrg return str; 591 1.1 mrg case 'i': 592 1.1 mrg if (match ("invmod", str)) 593 1.1 mrg { 594 1.1 mrg str = power (str + 6, &e2); 595 1.1 mrg makeexp (e, REM, *e, e2); 596 1.1 mrg break; 597 1.1 mrg } 598 1.1 mrg return str; 599 1.1 mrg case 't': 600 1.1 mrg if (match ("times", str)) 601 1.1 mrg { 602 1.1 mrg str = power (str + 5, &e2); 603 1.1 mrg makeexp (e, MULT, *e, e2); 604 1.1 mrg break; 605 1.1 mrg } 606 1.1 mrg if (match ("thru", str)) 607 1.1 mrg { 608 1.1 mrg str = power (str + 4, &e2); 609 1.1 mrg makeexp (e, DIV, *e, e2); 610 1.1 mrg break; 611 1.1 mrg } 612 1.1 mrg if (match ("through", str)) 613 1.1 mrg { 614 1.1 mrg str = power (str + 7, &e2); 615 1.1 mrg makeexp (e, DIV, *e, e2); 616 1.1 mrg break; 617 1.1 mrg } 618 1.1 mrg return str; 619 1.1 mrg case '*': 620 1.1 mrg str = power (str + 1, &e2); 621 1.1 mrg makeexp (e, MULT, *e, e2); 622 1.1 mrg break; 623 1.1 mrg case '/': 624 1.1 mrg str = power (str + 1, &e2); 625 1.1 mrg makeexp (e, DIV, *e, e2); 626 1.1 mrg break; 627 1.1 mrg case '%': 628 1.1 mrg str = power (str + 1, &e2); 629 1.1 mrg makeexp (e, MOD, *e, e2); 630 1.1 mrg break; 631 1.1 mrg default: 632 1.1 mrg return str; 633 1.1 mrg } 634 1.1 mrg } 635 1.1 mrg } 636 1.1 mrg 637 1.1 mrg char * 638 1.1 mrg power (char *str, expr_t *e) 639 1.1 mrg { 640 1.1 mrg expr_t e2; 641 1.1 mrg 642 1.1 mrg str = factor (str, e); 643 1.1 mrg while (str[0] == '!') 644 1.1 mrg { 645 1.1 mrg str++; 646 1.1 mrg makeexp (e, FAC, *e, NULL); 647 1.1 mrg } 648 1.1 mrg str = skipspace (str); 649 1.1 mrg if (str[0] == '^') 650 1.1 mrg { 651 1.1 mrg str = power (str + 1, &e2); 652 1.1 mrg makeexp (e, POW, *e, e2); 653 1.1 mrg } 654 1.1 mrg return str; 655 1.1 mrg } 656 1.1 mrg 657 1.1 mrg int 658 1.1 mrg match (char *s, char *str) 659 1.1 mrg { 660 1.1 mrg char *ostr = str; 661 1.1 mrg int i; 662 1.1 mrg 663 1.1 mrg for (i = 0; s[i] != 0; i++) 664 1.1 mrg { 665 1.1 mrg if (str[i] != s[i]) 666 1.1 mrg return 0; 667 1.1 mrg } 668 1.1 mrg str = skipspace (str + i); 669 1.1 mrg return str - ostr; 670 1.1 mrg } 671 1.1 mrg 672 1.1 mrg int 673 1.1 mrg matchp (char *s, char *str) 674 1.1 mrg { 675 1.1 mrg char *ostr = str; 676 1.1 mrg int i; 677 1.1 mrg 678 1.1 mrg for (i = 0; s[i] != 0; i++) 679 1.1 mrg { 680 1.1 mrg if (str[i] != s[i]) 681 1.1 mrg return 0; 682 1.1 mrg } 683 1.1 mrg str = skipspace (str + i); 684 1.1 mrg if (str[0] == '(') 685 1.1 mrg return str - ostr + 1; 686 1.1 mrg return 0; 687 1.1 mrg } 688 1.1 mrg 689 1.1 mrg struct functions 690 1.1 mrg { 691 1.1 mrg char *spelling; 692 1.1 mrg enum op_t op; 693 1.1 mrg int arity; /* 1 or 2 means real arity; 0 means arbitrary. */ 694 1.1 mrg }; 695 1.1 mrg 696 1.1 mrg struct functions fns[] = 697 1.1 mrg { 698 1.1 mrg {"sqrt", SQRT, 1}, 699 1.1 mrg #if __GNU_MP_VERSION >= 2 700 1.1 mrg {"root", ROOT, 2}, 701 1.1 mrg {"popc", POPCNT, 1}, 702 1.1 mrg {"hamdist", HAMDIST, 2}, 703 1.1 mrg #endif 704 1.1 mrg {"gcd", GCD, 0}, 705 1.1 mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 706 1.1 mrg {"lcm", LCM, 0}, 707 1.1 mrg #endif 708 1.1 mrg {"and", AND, 0}, 709 1.1 mrg {"ior", IOR, 0}, 710 1.1 mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 711 1.1 mrg {"xor", XOR, 0}, 712 1.1 mrg #endif 713 1.1 mrg {"plus", PLUS, 0}, 714 1.1 mrg {"pow", POW, 2}, 715 1.1 mrg {"minus", MINUS, 2}, 716 1.1 mrg {"mul", MULT, 0}, 717 1.1 mrg {"div", DIV, 2}, 718 1.1 mrg {"mod", MOD, 2}, 719 1.1 mrg {"rem", REM, 2}, 720 1.1 mrg #if __GNU_MP_VERSION >= 2 721 1.1 mrg {"invmod", INVMOD, 2}, 722 1.1 mrg #endif 723 1.1 mrg {"log", LOG, 2}, 724 1.1 mrg {"log2", LOG2, 1}, 725 1.1 mrg {"F", FERMAT, 1}, 726 1.1 mrg {"M", MERSENNE, 1}, 727 1.1 mrg {"fib", FIBONACCI, 1}, 728 1.1 mrg {"Fib", FIBONACCI, 1}, 729 1.1 mrg {"random", RANDOM, 1}, 730 1.1 mrg {"nextprime", NEXTPRIME, 1}, 731 1.1 mrg {"binom", BINOM, 2}, 732 1.1 mrg {"binomial", BINOM, 2}, 733 1.1 mrg {"fac", FAC, 1}, 734 1.1 mrg {"fact", FAC, 1}, 735 1.1 mrg {"factorial", FAC, 1}, 736 1.1 mrg {"time", TIMING, 1}, 737 1.1 mrg {"", NOP, 0} 738 1.1 mrg }; 739 1.1 mrg 740 1.1 mrg char * 741 1.1 mrg factor (char *str, expr_t *e) 742 1.1 mrg { 743 1.1 mrg expr_t e1, e2; 744 1.1 mrg 745 1.1 mrg str = skipspace (str); 746 1.1 mrg 747 1.1 mrg if (isalpha (str[0])) 748 1.1 mrg { 749 1.1 mrg int i; 750 1.1 mrg int cnt; 751 1.1 mrg 752 1.1 mrg for (i = 0; fns[i].op != NOP; i++) 753 1.1 mrg { 754 1.1 mrg if (fns[i].arity == 1) 755 1.1 mrg { 756 1.1 mrg cnt = matchp (fns[i].spelling, str); 757 1.1 mrg if (cnt != 0) 758 1.1 mrg { 759 1.1 mrg str = expr (str + cnt, &e1); 760 1.1 mrg str = skipspace (str); 761 1.1 mrg if (str[0] != ')') 762 1.1 mrg { 763 1.1 mrg error = "expected `)'"; 764 1.1 mrg longjmp (errjmpbuf, (int) (long) str); 765 1.1 mrg } 766 1.1 mrg makeexp (e, fns[i].op, e1, NULL); 767 1.1 mrg return str + 1; 768 1.1 mrg } 769 1.1 mrg } 770 1.1 mrg } 771 1.1 mrg 772 1.1 mrg for (i = 0; fns[i].op != NOP; i++) 773 1.1 mrg { 774 1.1 mrg if (fns[i].arity != 1) 775 1.1 mrg { 776 1.1 mrg cnt = matchp (fns[i].spelling, str); 777 1.1 mrg if (cnt != 0) 778 1.1 mrg { 779 1.1 mrg str = expr (str + cnt, &e1); 780 1.1 mrg str = skipspace (str); 781 1.1 mrg 782 1.1 mrg if (str[0] != ',') 783 1.1 mrg { 784 1.1 mrg error = "expected `,' and another operand"; 785 1.1 mrg longjmp (errjmpbuf, (int) (long) str); 786 1.1 mrg } 787 1.1 mrg 788 1.1 mrg str = skipspace (str + 1); 789 1.1 mrg str = expr (str, &e2); 790 1.1 mrg str = skipspace (str); 791 1.1 mrg 792 1.1 mrg if (fns[i].arity == 0) 793 1.1 mrg { 794 1.1 mrg while (str[0] == ',') 795 1.1 mrg { 796 1.1 mrg makeexp (&e1, fns[i].op, e1, e2); 797 1.1 mrg str = skipspace (str + 1); 798 1.1 mrg str = expr (str, &e2); 799 1.1 mrg str = skipspace (str); 800 1.1 mrg } 801 1.1 mrg } 802 1.1 mrg 803 1.1 mrg if (str[0] != ')') 804 1.1 mrg { 805 1.1 mrg error = "expected `)'"; 806 1.1 mrg longjmp (errjmpbuf, (int) (long) str); 807 1.1 mrg } 808 1.1 mrg 809 1.1 mrg makeexp (e, fns[i].op, e1, e2); 810 1.1 mrg return str + 1; 811 1.1 mrg } 812 1.1 mrg } 813 1.1 mrg } 814 1.1 mrg } 815 1.1 mrg 816 1.1 mrg if (str[0] == '(') 817 1.1 mrg { 818 1.1 mrg str = expr (str + 1, e); 819 1.1 mrg str = skipspace (str); 820 1.1 mrg if (str[0] != ')') 821 1.1 mrg { 822 1.1 mrg error = "expected `)'"; 823 1.1 mrg longjmp (errjmpbuf, (int) (long) str); 824 1.1 mrg } 825 1.1 mrg str++; 826 1.1 mrg } 827 1.1 mrg else if (str[0] >= '0' && str[0] <= '9') 828 1.1 mrg { 829 1.1 mrg expr_t res; 830 1.1 mrg char *s, *sc; 831 1.1 mrg 832 1.1 mrg res = malloc (sizeof (struct expr)); 833 1.1 mrg res -> op = LIT; 834 1.1 mrg mpz_init (res->operands.val); 835 1.1 mrg 836 1.1 mrg s = str; 837 1.1 mrg while (isalnum (str[0])) 838 1.1 mrg str++; 839 1.1 mrg sc = malloc (str - s + 1); 840 1.1 mrg memcpy (sc, s, str - s); 841 1.1 mrg sc[str - s] = 0; 842 1.1 mrg 843 1.1 mrg mpz_set_str (res->operands.val, sc, 0); 844 1.1 mrg *e = res; 845 1.1 mrg free (sc); 846 1.1 mrg } 847 1.1 mrg else 848 1.1 mrg { 849 1.1 mrg error = "operand expected"; 850 1.1 mrg longjmp (errjmpbuf, (int) (long) str); 851 1.1 mrg } 852 1.1 mrg return str; 853 1.1 mrg } 854 1.1 mrg 855 1.1 mrg char * 856 1.1 mrg skipspace (char *str) 857 1.1 mrg { 858 1.1 mrg while (str[0] == ' ') 859 1.1 mrg str++; 860 1.1 mrg return str; 861 1.1 mrg } 862 1.1 mrg 863 1.1 mrg /* Make a new expression with operation OP and right hand side 864 1.1 mrg RHS and left hand side lhs. Put the result in R. */ 865 1.1 mrg void 866 1.1 mrg makeexp (expr_t *r, enum op_t op, expr_t lhs, expr_t rhs) 867 1.1 mrg { 868 1.1 mrg expr_t res; 869 1.1 mrg res = malloc (sizeof (struct expr)); 870 1.1 mrg res -> op = op; 871 1.1 mrg res -> operands.ops.lhs = lhs; 872 1.1 mrg res -> operands.ops.rhs = rhs; 873 1.1 mrg *r = res; 874 1.1 mrg return; 875 1.1 mrg } 876 1.1 mrg 877 1.1 mrg /* Free the memory used by expression E. */ 878 1.1 mrg void 879 1.1 mrg free_expr (expr_t e) 880 1.1 mrg { 881 1.1 mrg if (e->op != LIT) 882 1.1 mrg { 883 1.1 mrg free_expr (e->operands.ops.lhs); 884 1.1 mrg if (e->operands.ops.rhs != NULL) 885 1.1 mrg free_expr (e->operands.ops.rhs); 886 1.1 mrg } 887 1.1 mrg else 888 1.1 mrg { 889 1.1 mrg mpz_clear (e->operands.val); 890 1.1 mrg } 891 1.1 mrg } 892 1.1 mrg 893 1.1 mrg /* Evaluate the expression E and put the result in R. */ 894 1.1 mrg void 895 1.1 mrg mpz_eval_expr (mpz_ptr r, expr_t e) 896 1.1 mrg { 897 1.1 mrg mpz_t lhs, rhs; 898 1.1 mrg 899 1.1 mrg switch (e->op) 900 1.1 mrg { 901 1.1 mrg case LIT: 902 1.1 mrg mpz_set (r, e->operands.val); 903 1.1 mrg return; 904 1.1 mrg case PLUS: 905 1.1 mrg mpz_init (lhs); mpz_init (rhs); 906 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 907 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 908 1.1 mrg mpz_add (r, lhs, rhs); 909 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 910 1.1 mrg return; 911 1.1 mrg case MINUS: 912 1.1 mrg mpz_init (lhs); mpz_init (rhs); 913 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 914 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 915 1.1 mrg mpz_sub (r, lhs, rhs); 916 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 917 1.1 mrg return; 918 1.1 mrg case MULT: 919 1.1 mrg mpz_init (lhs); mpz_init (rhs); 920 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 921 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 922 1.1 mrg mpz_mul (r, lhs, rhs); 923 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 924 1.1 mrg return; 925 1.1 mrg case DIV: 926 1.1 mrg mpz_init (lhs); mpz_init (rhs); 927 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 928 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 929 1.1 mrg mpz_fdiv_q (r, lhs, rhs); 930 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 931 1.1 mrg return; 932 1.1 mrg case MOD: 933 1.1 mrg mpz_init (rhs); 934 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 935 1.1 mrg mpz_abs (rhs, rhs); 936 1.1 mrg mpz_eval_mod_expr (r, e->operands.ops.lhs, rhs); 937 1.1 mrg mpz_clear (rhs); 938 1.1 mrg return; 939 1.1 mrg case REM: 940 1.1 mrg /* Check if lhs operand is POW expression and optimize for that case. */ 941 1.1 mrg if (e->operands.ops.lhs->op == POW) 942 1.1 mrg { 943 1.1 mrg mpz_t powlhs, powrhs; 944 1.1 mrg mpz_init (powlhs); 945 1.1 mrg mpz_init (powrhs); 946 1.1 mrg mpz_init (rhs); 947 1.1 mrg mpz_eval_expr (powlhs, e->operands.ops.lhs->operands.ops.lhs); 948 1.1 mrg mpz_eval_expr (powrhs, e->operands.ops.lhs->operands.ops.rhs); 949 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 950 1.1 mrg mpz_powm (r, powlhs, powrhs, rhs); 951 1.1 mrg if (mpz_cmp_si (rhs, 0L) < 0) 952 1.1 mrg mpz_neg (r, r); 953 1.1 mrg mpz_clear (powlhs); 954 1.1 mrg mpz_clear (powrhs); 955 1.1 mrg mpz_clear (rhs); 956 1.1 mrg return; 957 1.1 mrg } 958 1.1 mrg 959 1.1 mrg mpz_init (lhs); mpz_init (rhs); 960 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 961 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 962 1.1 mrg mpz_fdiv_r (r, lhs, rhs); 963 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 964 1.1 mrg return; 965 1.1 mrg #if __GNU_MP_VERSION >= 2 966 1.1 mrg case INVMOD: 967 1.1 mrg mpz_init (lhs); mpz_init (rhs); 968 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 969 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 970 1.1 mrg mpz_invert (r, lhs, rhs); 971 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 972 1.1 mrg return; 973 1.1 mrg #endif 974 1.1 mrg case POW: 975 1.1 mrg mpz_init (lhs); mpz_init (rhs); 976 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 977 1.1 mrg if (mpz_cmpabs_ui (lhs, 1) <= 0) 978 1.1 mrg { 979 1.1 mrg /* For 0^rhs and 1^rhs, we just need to verify that 980 1.1 mrg rhs is well-defined. For (-1)^rhs we need to 981 1.1 mrg determine (rhs mod 2). For simplicity, compute 982 1.1 mrg (rhs mod 2) for all three cases. */ 983 1.1 mrg expr_t two, et; 984 1.1 mrg two = malloc (sizeof (struct expr)); 985 1.1 mrg two -> op = LIT; 986 1.1 mrg mpz_init_set_ui (two->operands.val, 2L); 987 1.1 mrg makeexp (&et, MOD, e->operands.ops.rhs, two); 988 1.1 mrg e->operands.ops.rhs = et; 989 1.1 mrg } 990 1.1 mrg 991 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 992 1.1 mrg if (mpz_cmp_si (rhs, 0L) == 0) 993 1.1 mrg /* x^0 is 1 */ 994 1.1 mrg mpz_set_ui (r, 1L); 995 1.1 mrg else if (mpz_cmp_si (lhs, 0L) == 0) 996 1.1 mrg /* 0^y (where y != 0) is 0 */ 997 1.1 mrg mpz_set_ui (r, 0L); 998 1.1 mrg else if (mpz_cmp_ui (lhs, 1L) == 0) 999 1.1 mrg /* 1^y is 1 */ 1000 1.1 mrg mpz_set_ui (r, 1L); 1001 1.1 mrg else if (mpz_cmp_si (lhs, -1L) == 0) 1002 1.1 mrg /* (-1)^y just depends on whether y is even or odd */ 1003 1.1 mrg mpz_set_si (r, (mpz_get_ui (rhs) & 1) ? -1L : 1L); 1004 1.1 mrg else if (mpz_cmp_si (rhs, 0L) < 0) 1005 1.1 mrg /* x^(-n) is 0 */ 1006 1.1 mrg mpz_set_ui (r, 0L); 1007 1.1 mrg else 1008 1.1 mrg { 1009 1.1 mrg unsigned long int cnt; 1010 1.1 mrg unsigned long int y; 1011 1.1 mrg /* error if exponent does not fit into an unsigned long int. */ 1012 1.1 mrg if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) 1013 1.1 mrg goto pow_err; 1014 1.1 mrg 1015 1.1 mrg y = mpz_get_ui (rhs); 1016 1.1 mrg /* x^y == (x/(2^c))^y * 2^(c*y) */ 1017 1.1 mrg #if __GNU_MP_VERSION >= 2 1018 1.1 mrg cnt = mpz_scan1 (lhs, 0); 1019 1.1 mrg #else 1020 1.1 mrg cnt = 0; 1021 1.1 mrg #endif 1022 1.1 mrg if (cnt != 0) 1023 1.1 mrg { 1024 1.1 mrg if (y * cnt / cnt != y) 1025 1.1 mrg goto pow_err; 1026 1.1 mrg mpz_tdiv_q_2exp (lhs, lhs, cnt); 1027 1.1 mrg mpz_pow_ui (r, lhs, y); 1028 1.1 mrg mpz_mul_2exp (r, r, y * cnt); 1029 1.1 mrg } 1030 1.1 mrg else 1031 1.1 mrg mpz_pow_ui (r, lhs, y); 1032 1.1 mrg } 1033 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1034 1.1 mrg return; 1035 1.1 mrg pow_err: 1036 1.1 mrg error = "result of `pow' operator too large"; 1037 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1038 1.1 mrg longjmp (errjmpbuf, 1); 1039 1.1 mrg case GCD: 1040 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1041 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1042 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 1043 1.1 mrg mpz_gcd (r, lhs, rhs); 1044 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1045 1.1 mrg return; 1046 1.1 mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 1047 1.1 mrg case LCM: 1048 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1049 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1050 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 1051 1.1 mrg mpz_lcm (r, lhs, rhs); 1052 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1053 1.1 mrg return; 1054 1.1 mrg #endif 1055 1.1 mrg case AND: 1056 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1057 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1058 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 1059 1.1 mrg mpz_and (r, lhs, rhs); 1060 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1061 1.1 mrg return; 1062 1.1 mrg case IOR: 1063 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1064 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1065 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 1066 1.1 mrg mpz_ior (r, lhs, rhs); 1067 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1068 1.1 mrg return; 1069 1.1 mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 1070 1.1 mrg case XOR: 1071 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1072 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1073 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 1074 1.1 mrg mpz_xor (r, lhs, rhs); 1075 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1076 1.1 mrg return; 1077 1.1 mrg #endif 1078 1.1 mrg case NEG: 1079 1.1 mrg mpz_eval_expr (r, e->operands.ops.lhs); 1080 1.1 mrg mpz_neg (r, r); 1081 1.1 mrg return; 1082 1.1 mrg case NOT: 1083 1.1 mrg mpz_eval_expr (r, e->operands.ops.lhs); 1084 1.1 mrg mpz_com (r, r); 1085 1.1 mrg return; 1086 1.1 mrg case SQRT: 1087 1.1 mrg mpz_init (lhs); 1088 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1089 1.1 mrg if (mpz_sgn (lhs) < 0) 1090 1.1 mrg { 1091 1.1 mrg error = "cannot take square root of negative numbers"; 1092 1.1 mrg mpz_clear (lhs); 1093 1.1 mrg longjmp (errjmpbuf, 1); 1094 1.1 mrg } 1095 1.1 mrg mpz_sqrt (r, lhs); 1096 1.1 mrg return; 1097 1.1 mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 1098 1.1 mrg case ROOT: 1099 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1100 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1101 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 1102 1.1 mrg if (mpz_sgn (rhs) <= 0) 1103 1.1 mrg { 1104 1.1 mrg error = "cannot take non-positive root orders"; 1105 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1106 1.1 mrg longjmp (errjmpbuf, 1); 1107 1.1 mrg } 1108 1.1 mrg if (mpz_sgn (lhs) < 0 && (mpz_get_ui (rhs) & 1) == 0) 1109 1.1 mrg { 1110 1.1 mrg error = "cannot take even root orders of negative numbers"; 1111 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1112 1.1 mrg longjmp (errjmpbuf, 1); 1113 1.1 mrg } 1114 1.1 mrg 1115 1.1 mrg { 1116 1.1 mrg unsigned long int nth = mpz_get_ui (rhs); 1117 1.1 mrg if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) 1118 1.1 mrg { 1119 1.1 mrg /* If we are asked to take an awfully large root order, cheat and 1120 1.1 mrg ask for the largest order we can pass to mpz_root. This saves 1121 1.1 mrg some error prone special cases. */ 1122 1.1 mrg nth = ~(unsigned long int) 0; 1123 1.1 mrg } 1124 1.1 mrg mpz_root (r, lhs, nth); 1125 1.1 mrg } 1126 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1127 1.1 mrg return; 1128 1.1 mrg #endif 1129 1.1 mrg case FAC: 1130 1.1 mrg mpz_eval_expr (r, e->operands.ops.lhs); 1131 1.1 mrg if (mpz_size (r) > 1) 1132 1.1 mrg { 1133 1.1 mrg error = "result of `!' operator too large"; 1134 1.1 mrg longjmp (errjmpbuf, 1); 1135 1.1 mrg } 1136 1.1 mrg mpz_fac_ui (r, mpz_get_ui (r)); 1137 1.1 mrg return; 1138 1.1 mrg #if __GNU_MP_VERSION >= 2 1139 1.1 mrg case POPCNT: 1140 1.1 mrg mpz_eval_expr (r, e->operands.ops.lhs); 1141 1.1 mrg { long int cnt; 1142 1.1 mrg cnt = mpz_popcount (r); 1143 1.1 mrg mpz_set_si (r, cnt); 1144 1.1 mrg } 1145 1.1 mrg return; 1146 1.1 mrg case HAMDIST: 1147 1.1 mrg { long int cnt; 1148 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1149 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1150 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 1151 1.1 mrg cnt = mpz_hamdist (lhs, rhs); 1152 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1153 1.1 mrg mpz_set_si (r, cnt); 1154 1.1 mrg } 1155 1.1 mrg return; 1156 1.1 mrg #endif 1157 1.1 mrg case LOG2: 1158 1.1 mrg mpz_eval_expr (r, e->operands.ops.lhs); 1159 1.1 mrg { unsigned long int cnt; 1160 1.1 mrg if (mpz_sgn (r) <= 0) 1161 1.1 mrg { 1162 1.1 mrg error = "logarithm of non-positive number"; 1163 1.1 mrg longjmp (errjmpbuf, 1); 1164 1.1 mrg } 1165 1.1 mrg cnt = mpz_sizeinbase (r, 2); 1166 1.1 mrg mpz_set_ui (r, cnt - 1); 1167 1.1 mrg } 1168 1.1 mrg return; 1169 1.1 mrg case LOG: 1170 1.1 mrg { unsigned long int cnt; 1171 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1172 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1173 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 1174 1.1 mrg if (mpz_sgn (lhs) <= 0) 1175 1.1 mrg { 1176 1.1 mrg error = "logarithm of non-positive number"; 1177 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1178 1.1 mrg longjmp (errjmpbuf, 1); 1179 1.1 mrg } 1180 1.1 mrg if (mpz_cmp_ui (rhs, 256) >= 0) 1181 1.1 mrg { 1182 1.1 mrg error = "logarithm base too large"; 1183 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1184 1.1 mrg longjmp (errjmpbuf, 1); 1185 1.1 mrg } 1186 1.1 mrg cnt = mpz_sizeinbase (lhs, mpz_get_ui (rhs)); 1187 1.1 mrg mpz_set_ui (r, cnt - 1); 1188 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1189 1.1 mrg } 1190 1.1 mrg return; 1191 1.1 mrg case FERMAT: 1192 1.1 mrg { 1193 1.1 mrg unsigned long int t; 1194 1.1 mrg mpz_init (lhs); 1195 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1196 1.1 mrg t = (unsigned long int) 1 << mpz_get_ui (lhs); 1197 1.1 mrg if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0 || t == 0) 1198 1.1 mrg { 1199 1.1 mrg error = "too large Mersenne number index"; 1200 1.1 mrg mpz_clear (lhs); 1201 1.1 mrg longjmp (errjmpbuf, 1); 1202 1.1 mrg } 1203 1.1 mrg mpz_set_ui (r, 1); 1204 1.1 mrg mpz_mul_2exp (r, r, t); 1205 1.1 mrg mpz_add_ui (r, r, 1); 1206 1.1 mrg mpz_clear (lhs); 1207 1.1 mrg } 1208 1.1 mrg return; 1209 1.1 mrg case MERSENNE: 1210 1.1 mrg mpz_init (lhs); 1211 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1212 1.1 mrg if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0) 1213 1.1 mrg { 1214 1.1 mrg error = "too large Mersenne number index"; 1215 1.1 mrg mpz_clear (lhs); 1216 1.1 mrg longjmp (errjmpbuf, 1); 1217 1.1 mrg } 1218 1.1 mrg mpz_set_ui (r, 1); 1219 1.1 mrg mpz_mul_2exp (r, r, mpz_get_ui (lhs)); 1220 1.1 mrg mpz_sub_ui (r, r, 1); 1221 1.1 mrg mpz_clear (lhs); 1222 1.1 mrg return; 1223 1.1 mrg case FIBONACCI: 1224 1.1 mrg { mpz_t t; 1225 1.1 mrg unsigned long int n, i; 1226 1.1 mrg mpz_init (lhs); 1227 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1228 1.1 mrg if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0) 1229 1.1 mrg { 1230 1.1 mrg error = "Fibonacci index out of range"; 1231 1.1 mrg mpz_clear (lhs); 1232 1.1 mrg longjmp (errjmpbuf, 1); 1233 1.1 mrg } 1234 1.1 mrg n = mpz_get_ui (lhs); 1235 1.1 mrg mpz_clear (lhs); 1236 1.1 mrg 1237 1.1 mrg #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 1238 1.1 mrg mpz_fib_ui (r, n); 1239 1.1 mrg #else 1240 1.1 mrg mpz_init_set_ui (t, 1); 1241 1.1 mrg mpz_set_ui (r, 1); 1242 1.1 mrg 1243 1.1 mrg if (n <= 2) 1244 1.1 mrg mpz_set_ui (r, 1); 1245 1.1 mrg else 1246 1.1 mrg { 1247 1.1 mrg for (i = 3; i <= n; i++) 1248 1.1 mrg { 1249 1.1 mrg mpz_add (t, t, r); 1250 1.1 mrg mpz_swap (t, r); 1251 1.1 mrg } 1252 1.1 mrg } 1253 1.1 mrg mpz_clear (t); 1254 1.1 mrg #endif 1255 1.1 mrg } 1256 1.1 mrg return; 1257 1.1 mrg case RANDOM: 1258 1.1 mrg { 1259 1.1 mrg unsigned long int n; 1260 1.1 mrg mpz_init (lhs); 1261 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1262 1.1 mrg if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0) 1263 1.1 mrg { 1264 1.1 mrg error = "random number size out of range"; 1265 1.1 mrg mpz_clear (lhs); 1266 1.1 mrg longjmp (errjmpbuf, 1); 1267 1.1 mrg } 1268 1.1 mrg n = mpz_get_ui (lhs); 1269 1.1 mrg mpz_clear (lhs); 1270 1.1 mrg mpz_urandomb (r, rstate, n); 1271 1.1 mrg } 1272 1.1 mrg return; 1273 1.1 mrg case NEXTPRIME: 1274 1.1 mrg { 1275 1.1 mrg mpz_eval_expr (r, e->operands.ops.lhs); 1276 1.1 mrg mpz_nextprime (r, r); 1277 1.1 mrg } 1278 1.1 mrg return; 1279 1.1 mrg case BINOM: 1280 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1281 1.1 mrg mpz_eval_expr (lhs, e->operands.ops.lhs); 1282 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 1283 1.1 mrg { 1284 1.1 mrg unsigned long int k; 1285 1.1 mrg if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) 1286 1.1 mrg { 1287 1.1 mrg error = "k too large in (n over k) expression"; 1288 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1289 1.1 mrg longjmp (errjmpbuf, 1); 1290 1.1 mrg } 1291 1.1 mrg k = mpz_get_ui (rhs); 1292 1.1 mrg mpz_bin_ui (r, lhs, k); 1293 1.1 mrg } 1294 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1295 1.1 mrg return; 1296 1.1 mrg case TIMING: 1297 1.1 mrg { 1298 1.1 mrg int t0; 1299 1.1 mrg t0 = cputime (); 1300 1.1 mrg mpz_eval_expr (r, e->operands.ops.lhs); 1301 1.1 mrg printf ("time: %d\n", cputime () - t0); 1302 1.1 mrg } 1303 1.1 mrg return; 1304 1.1 mrg default: 1305 1.1 mrg abort (); 1306 1.1 mrg } 1307 1.1 mrg } 1308 1.1 mrg 1309 1.1 mrg /* Evaluate the expression E modulo MOD and put the result in R. */ 1310 1.1 mrg void 1311 1.1 mrg mpz_eval_mod_expr (mpz_ptr r, expr_t e, mpz_ptr mod) 1312 1.1 mrg { 1313 1.1 mrg mpz_t lhs, rhs; 1314 1.1 mrg 1315 1.1 mrg switch (e->op) 1316 1.1 mrg { 1317 1.1 mrg case POW: 1318 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1319 1.1 mrg mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod); 1320 1.1 mrg mpz_eval_expr (rhs, e->operands.ops.rhs); 1321 1.1 mrg mpz_powm (r, lhs, rhs, mod); 1322 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1323 1.1 mrg return; 1324 1.1 mrg case PLUS: 1325 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1326 1.1 mrg mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod); 1327 1.1 mrg mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod); 1328 1.1 mrg mpz_add (r, lhs, rhs); 1329 1.1 mrg if (mpz_cmp_si (r, 0L) < 0) 1330 1.1 mrg mpz_add (r, r, mod); 1331 1.1 mrg else if (mpz_cmp (r, mod) >= 0) 1332 1.1 mrg mpz_sub (r, r, mod); 1333 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1334 1.1 mrg return; 1335 1.1 mrg case MINUS: 1336 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1337 1.1 mrg mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod); 1338 1.1 mrg mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod); 1339 1.1 mrg mpz_sub (r, lhs, rhs); 1340 1.1 mrg if (mpz_cmp_si (r, 0L) < 0) 1341 1.1 mrg mpz_add (r, r, mod); 1342 1.1 mrg else if (mpz_cmp (r, mod) >= 0) 1343 1.1 mrg mpz_sub (r, r, mod); 1344 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1345 1.1 mrg return; 1346 1.1 mrg case MULT: 1347 1.1 mrg mpz_init (lhs); mpz_init (rhs); 1348 1.1 mrg mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod); 1349 1.1 mrg mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod); 1350 1.1 mrg mpz_mul (r, lhs, rhs); 1351 1.1 mrg mpz_mod (r, r, mod); 1352 1.1 mrg mpz_clear (lhs); mpz_clear (rhs); 1353 1.1 mrg return; 1354 1.1 mrg default: 1355 1.1 mrg mpz_init (lhs); 1356 1.1 mrg mpz_eval_expr (lhs, e); 1357 1.1 mrg mpz_mod (r, lhs, mod); 1358 1.1 mrg mpz_clear (lhs); 1359 1.1 mrg return; 1360 1.1 mrg } 1361 1.1 mrg } 1362 1.1 mrg 1363 1.1 mrg void 1364 1.1 mrg cleanup_and_exit (int sig) 1365 1.1 mrg { 1366 1.1 mrg switch (sig) { 1367 1.1 mrg #ifdef LIMIT_RESOURCE_USAGE 1368 1.1 mrg case SIGXCPU: 1369 1.1 mrg printf ("expression took too long to evaluate%s\n", newline); 1370 1.1 mrg break; 1371 1.1 mrg #endif 1372 1.1 mrg case SIGFPE: 1373 1.1 mrg printf ("divide by zero%s\n", newline); 1374 1.1 mrg break; 1375 1.1 mrg default: 1376 1.1 mrg printf ("expression required too much memory to evaluate%s\n", newline); 1377 1.1 mrg break; 1378 1.1 mrg } 1379 1.1 mrg exit (-2); 1380 1.1 mrg } 1381