1 /* Program for computing integer expressions using the GNU Multiple Precision
4 Copyright 1997, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free Software
8 Foundation; either version 3 of the License, or (at your option) any later
11 This program is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along with
16 this program. If not, see http://www.gnu.org/licenses/. */
19 /* This expressions evaluator works by building an expression tree (using a
20 recursive descent parser) which is then evaluated. The expression tree is
21 useful since we want to optimize certain expressions (like a^b % c).
23 Usage: pexpr [options] expr ...
24 (Assuming you called the executable `pexpr' of course.)
28 -b print output in binary
29 -o print output in octal
30 -d print output in decimal (the default)
31 -x print output in hexadecimal
32 -b<NUM> print output in base NUM
33 -t print timing information
36 -split split long lines each 80th digit
39 /* Define LIMIT_RESOURCE_USAGE if you want to make sure the program doesn't
40 use up extensive resources (cpu, memory). Useful for the GMP demo on the
41 GMP web site, since we cannot load the server too much. */
43 #include "pexpr-config.h"
53 #include <sys/types.h>
55 #if HAVE_SYS_RESOURCE_H
56 #include <sys/resource.h>
61 /* SunOS 4 and HPUX 9 don't define a canonical SIGSTKSZ, use a default. */
67 #define TIME(t,func) \
68 do { int __t0, __tmp; \
71 __tmp = cputime () - __t0; \
75 /* GMP version 1.x compatibility. */
76 #if ! (__GNU_MP_VERSION >= 2)
77 typedef MP_INT __mpz_struct;
78 typedef __mpz_struct mpz_t[1];
79 typedef __mpz_struct *mpz_ptr;
80 #define mpz_fdiv_q mpz_div
81 #define mpz_fdiv_r mpz_mod
82 #define mpz_tdiv_q_2exp mpz_div_2exp
83 #define mpz_sgn(Z) ((Z)->size < 0 ? -1 : (Z)->size > 0)
86 /* GMP version 2.0 compatibility. */
87 #if ! (__GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1)
88 #define mpz_swap(a,b) \
89 do { __mpz_struct __t; __t = *a; *a = *b; *b = __t;} while (0)
94 enum op_t {NOP, LIT, NEG, NOT, PLUS, MINUS, MULT, DIV, MOD, REM, INVMOD, POW,
95 AND, IOR, XOR, SLL, SRA, POPCNT, HAMDIST, GCD, LCM, SQRT, ROOT, FAC,
96 LOG, LOG2, FERMAT, MERSENNE, FIBONACCI, RANDOM, NEXTPRIME, BINOM,
99 /* Type for the expression tree. */
105 struct {struct expr *lhs, *rhs;} ops;
110 typedef struct expr *expr_t;
112 void cleanup_and_exit __GMP_PROTO ((int));
114 char *skipspace __GMP_PROTO ((char *));
115 void makeexp __GMP_PROTO ((expr_t *, enum op_t, expr_t, expr_t));
116 void free_expr __GMP_PROTO ((expr_t));
117 char *expr __GMP_PROTO ((char *, expr_t *));
118 char *term __GMP_PROTO ((char *, expr_t *));
119 char *power __GMP_PROTO ((char *, expr_t *));
120 char *factor __GMP_PROTO ((char *, expr_t *));
121 int match __GMP_PROTO ((char *, char *));
122 int matchp __GMP_PROTO ((char *, char *));
123 int cputime __GMP_PROTO ((void));
125 void mpz_eval_expr __GMP_PROTO ((mpz_ptr, expr_t));
126 void mpz_eval_mod_expr __GMP_PROTO ((mpz_ptr, expr_t, mpz_ptr));
130 int print_timing = 0;
133 int flag_splitup_output = 0;
135 gmp_randstate_t rstate;
139 /* cputime() returns user CPU time measured in milliseconds. */
148 return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
155 if (CLOCKS_PER_SEC < 100000)
156 return clock () * 1000 / CLOCKS_PER_SEC;
157 return clock () / (CLOCKS_PER_SEC / 1000);
171 stack_downwards_helper (char *xp)
177 stack_downwards_p (void)
180 return stack_downwards_helper (&x);
185 setup_error_handler (void)
188 struct sigaction act;
189 act.sa_handler = cleanup_and_exit;
190 sigemptyset (&(act.sa_mask));
191 #define SIGNAL(sig) sigaction (sig, &act, NULL)
193 struct { int sa_flags; } act;
194 #define SIGNAL(sig) signal (sig, cleanup_and_exit)
198 /* Set up a stack for signal handling. A typical cause of error is stack
199 overflow, and in such situation a signal can not be delivered on the
203 /* AIX uses stack_t, MacOS uses struct sigaltstack, various other
204 systems have both. */
208 struct sigaltstack s;
210 s.ss_sp = malloc (SIGSTKSZ);
211 s.ss_size = SIGSTKSZ;
213 if (sigaltstack (&s, NULL) != 0)
214 perror("sigaltstack");
215 act.sa_flags = SA_ONSTACK;
221 s.ss_sp = malloc (SIGSTKSZ);
222 if (stack_downwards_p ())
225 if (sigstack (&s, NULL) != 0)
227 act.sa_flags = SA_ONSTACK;
233 #ifdef LIMIT_RESOURCE_USAGE
237 limit.rlim_cur = limit.rlim_max = 0;
238 setrlimit (RLIMIT_CORE, &limit);
242 setrlimit (RLIMIT_CPU, &limit);
244 limit.rlim_cur = limit.rlim_max = 16 * 1024 * 1024;
245 setrlimit (RLIMIT_DATA, &limit);
247 getrlimit (RLIMIT_STACK, &limit);
248 limit.rlim_cur = 4 * 1024 * 1024;
249 setrlimit (RLIMIT_STACK, &limit);
253 #endif /* LIMIT_RESOURCE_USAGE */
257 #ifdef SIGBUS /* not in mingw */
265 main (int argc, char **argv)
274 setup_error_handler ();
276 gmp_randinit (rstate, GMP_RAND_ALG_LC, 128);
279 #if HAVE_GETTIMEOFDAY
281 gettimeofday (&tv, NULL);
282 gmp_randseed_ui (rstate, tv.tv_sec + tv.tv_usec);
286 gmp_randseed_ui (rstate, t);
292 while (argc > 1 && argv[1][0] == '-')
296 if (arg[1] >= '0' && arg[1] <= '9')
301 else if (arg[1] == 'b' && arg[2] >= '0' && arg[2] <= '9')
303 base = atoi (arg + 2);
304 if (base < 2 || base > 62)
306 fprintf (stderr, "error: invalid output base\n");
310 else if (arg[1] == 'b' && arg[2] == 0)
312 else if (arg[1] == 'x' && arg[2] == 0)
314 else if (arg[1] == 'X' && arg[2] == 0)
316 else if (arg[1] == 'o' && arg[2] == 0)
318 else if (arg[1] == 'd' && arg[2] == 0)
320 else if (arg[1] == 'v' && arg[2] == 0)
322 printf ("pexpr linked to gmp %s\n", __gmp_version);
324 else if (strcmp (arg, "-html") == 0)
329 else if (strcmp (arg, "-wml") == 0)
334 else if (strcmp (arg, "-split") == 0)
336 flag_splitup_output = 1;
338 else if (strcmp (arg, "-noprint") == 0)
344 fprintf (stderr, "error: unknown option `%s'\n", arg);
351 for (i = 1; i < argc; i++)
356 /* Set up error handler for parsing expression. */
357 jmpval = setjmp (errjmpbuf);
360 fprintf (stderr, "error: %s%s\n", error, newline);
361 fprintf (stderr, " %s%s\n", argv[i], newline);
364 /* ??? Dunno how to align expression position with arrow in
366 fprintf (stderr, " ");
367 for (s = jmpval - (long) argv[i]; --s >= 0; )
369 fprintf (stderr, "^\n");
376 str = expr (argv[i], &e);
381 "error: garbage where end of expression expected%s\n",
383 fprintf (stderr, " %s%s\n", argv[i], newline);
386 /* ??? Dunno how to align expression position with arrow in
388 fprintf (stderr, " ");
389 for (s = str - argv[i]; --s; )
391 fprintf (stderr, "^\n");
399 /* Set up error handler for evaluating expression. */
400 if (setjmp (errjmpbuf))
402 fprintf (stderr, "error: %s%s\n", error, newline);
403 fprintf (stderr, " %s%s\n", argv[i], newline);
406 /* ??? Dunno how to align expression position with arrow in
408 fprintf (stderr, " ");
409 for (s = str - argv[i]; --s >= 0; )
411 fprintf (stderr, "^\n");
421 TIME (t, mpz_eval_expr (r, e));
422 printf ("computation took %d ms%s\n", t, newline);
425 mpz_eval_expr (r, e);
432 out_len = mpz_sizeinbase (r, base >= 0 ? base : -base) + 2;
433 #ifdef LIMIT_RESOURCE_USAGE
434 if (out_len > 100000)
436 printf ("result is about %ld digits, not printing it%s\n",
437 (long) out_len - 3, newline);
441 tmp = malloc (out_len);
446 printf ("output conversion ");
447 TIME (t, mpz_get_str (tmp, base, r));
448 printf ("took %d ms%s\n", t, newline);
451 mpz_get_str (tmp, base, r);
453 out_len = strlen (tmp);
454 if (flag_splitup_output)
456 for (s = tmp; out_len > 80; s += 80)
458 fwrite (s, 1, 80, stdout);
459 printf ("%s\n", newline);
463 fwrite (s, 1, out_len, stdout);
467 fwrite (tmp, 1, out_len, stdout);
471 printf ("%s\n", newline);
475 printf ("result is approximately %ld digits%s\n",
476 (long) mpz_sizeinbase (r, base >= 0 ? base : -base),
487 expr (char *str, expr_t *e)
491 str = skipspace (str);
494 str = term (str + 1, e);
496 else if (str[0] == '-')
498 str = term (str + 1, e);
499 makeexp (e, NEG, *e, NULL);
501 else if (str[0] == '~')
503 str = term (str + 1, e);
504 makeexp (e, NOT, *e, NULL);
513 str = skipspace (str);
517 if (match ("plus", str))
519 str = term (str + 4, &e2);
520 makeexp (e, PLUS, *e, e2);
526 if (match ("minus", str))
528 str = term (str + 5, &e2);
529 makeexp (e, MINUS, *e, e2);
535 str = term (str + 1, &e2);
536 makeexp (e, PLUS, *e, e2);
539 str = term (str + 1, &e2);
540 makeexp (e, MINUS, *e, e2);
549 term (char *str, expr_t *e)
553 str = power (str, e);
556 str = skipspace (str);
560 if (match ("mul", str))
562 str = power (str + 3, &e2);
563 makeexp (e, MULT, *e, e2);
566 if (match ("mod", str))
568 str = power (str + 3, &e2);
569 makeexp (e, MOD, *e, e2);
574 if (match ("div", str))
576 str = power (str + 3, &e2);
577 makeexp (e, DIV, *e, e2);
582 if (match ("rem", str))
584 str = power (str + 3, &e2);
585 makeexp (e, REM, *e, e2);
590 if (match ("invmod", str))
592 str = power (str + 6, &e2);
593 makeexp (e, REM, *e, e2);
598 if (match ("times", str))
600 str = power (str + 5, &e2);
601 makeexp (e, MULT, *e, e2);
604 if (match ("thru", str))
606 str = power (str + 4, &e2);
607 makeexp (e, DIV, *e, e2);
610 if (match ("through", str))
612 str = power (str + 7, &e2);
613 makeexp (e, DIV, *e, e2);
618 str = power (str + 1, &e2);
619 makeexp (e, MULT, *e, e2);
622 str = power (str + 1, &e2);
623 makeexp (e, DIV, *e, e2);
626 str = power (str + 1, &e2);
627 makeexp (e, MOD, *e, e2);
636 power (char *str, expr_t *e)
640 str = factor (str, e);
641 while (str[0] == '!')
644 makeexp (e, FAC, *e, NULL);
646 str = skipspace (str);
649 str = power (str + 1, &e2);
650 makeexp (e, POW, *e, e2);
656 match (char *s, char *str)
661 for (i = 0; s[i] != 0; i++)
666 str = skipspace (str + i);
671 matchp (char *s, char *str)
676 for (i = 0; s[i] != 0; i++)
681 str = skipspace (str + i);
683 return str - ostr + 1;
691 int arity; /* 1 or 2 means real arity; 0 means arbitrary. */
694 struct functions fns[] =
697 #if __GNU_MP_VERSION >= 2
700 {"hamdist", HAMDIST, 2},
703 #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
708 #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
718 #if __GNU_MP_VERSION >= 2
719 {"invmod", INVMOD, 2},
725 {"fib", FIBONACCI, 1},
726 {"Fib", FIBONACCI, 1},
727 {"random", RANDOM, 1},
728 {"nextprime", NEXTPRIME, 1},
730 {"binomial", BINOM, 2},
733 {"factorial", FAC, 1},
739 factor (char *str, expr_t *e)
743 str = skipspace (str);
745 if (isalpha (str[0]))
750 for (i = 0; fns[i].op != NOP; i++)
752 if (fns[i].arity == 1)
754 cnt = matchp (fns[i].spelling, str);
757 str = expr (str + cnt, &e1);
758 str = skipspace (str);
761 error = "expected `)'";
762 longjmp (errjmpbuf, (int) (long) str);
764 makeexp (e, fns[i].op, e1, NULL);
770 for (i = 0; fns[i].op != NOP; i++)
772 if (fns[i].arity != 1)
774 cnt = matchp (fns[i].spelling, str);
777 str = expr (str + cnt, &e1);
778 str = skipspace (str);
782 error = "expected `,' and another operand";
783 longjmp (errjmpbuf, (int) (long) str);
786 str = skipspace (str + 1);
787 str = expr (str, &e2);
788 str = skipspace (str);
790 if (fns[i].arity == 0)
792 while (str[0] == ',')
794 makeexp (&e1, fns[i].op, e1, e2);
795 str = skipspace (str + 1);
796 str = expr (str, &e2);
797 str = skipspace (str);
803 error = "expected `)'";
804 longjmp (errjmpbuf, (int) (long) str);
807 makeexp (e, fns[i].op, e1, e2);
816 str = expr (str + 1, e);
817 str = skipspace (str);
820 error = "expected `)'";
821 longjmp (errjmpbuf, (int) (long) str);
825 else if (str[0] >= '0' && str[0] <= '9')
830 res = malloc (sizeof (struct expr));
832 mpz_init (res->operands.val);
835 while (isalnum (str[0]))
837 sc = malloc (str - s + 1);
838 memcpy (sc, s, str - s);
841 mpz_set_str (res->operands.val, sc, 0);
847 error = "operand expected";
848 longjmp (errjmpbuf, (int) (long) str);
854 skipspace (char *str)
856 while (str[0] == ' ')
861 /* Make a new expression with operation OP and right hand side
862 RHS and left hand side lhs. Put the result in R. */
864 makeexp (expr_t *r, enum op_t op, expr_t lhs, expr_t rhs)
867 res = malloc (sizeof (struct expr));
869 res -> operands.ops.lhs = lhs;
870 res -> operands.ops.rhs = rhs;
875 /* Free the memory used by expression E. */
881 free_expr (e->operands.ops.lhs);
882 if (e->operands.ops.rhs != NULL)
883 free_expr (e->operands.ops.rhs);
887 mpz_clear (e->operands.val);
891 /* Evaluate the expression E and put the result in R. */
893 mpz_eval_expr (mpz_ptr r, expr_t e)
900 mpz_set (r, e->operands.val);
903 mpz_init (lhs); mpz_init (rhs);
904 mpz_eval_expr (lhs, e->operands.ops.lhs);
905 mpz_eval_expr (rhs, e->operands.ops.rhs);
906 mpz_add (r, lhs, rhs);
907 mpz_clear (lhs); mpz_clear (rhs);
910 mpz_init (lhs); mpz_init (rhs);
911 mpz_eval_expr (lhs, e->operands.ops.lhs);
912 mpz_eval_expr (rhs, e->operands.ops.rhs);
913 mpz_sub (r, lhs, rhs);
914 mpz_clear (lhs); mpz_clear (rhs);
917 mpz_init (lhs); mpz_init (rhs);
918 mpz_eval_expr (lhs, e->operands.ops.lhs);
919 mpz_eval_expr (rhs, e->operands.ops.rhs);
920 mpz_mul (r, lhs, rhs);
921 mpz_clear (lhs); mpz_clear (rhs);
924 mpz_init (lhs); mpz_init (rhs);
925 mpz_eval_expr (lhs, e->operands.ops.lhs);
926 mpz_eval_expr (rhs, e->operands.ops.rhs);
927 mpz_fdiv_q (r, lhs, rhs);
928 mpz_clear (lhs); mpz_clear (rhs);
932 mpz_eval_expr (rhs, e->operands.ops.rhs);
934 mpz_eval_mod_expr (r, e->operands.ops.lhs, rhs);
938 /* Check if lhs operand is POW expression and optimize for that case. */
939 if (e->operands.ops.lhs->op == POW)
941 mpz_t powlhs, powrhs;
945 mpz_eval_expr (powlhs, e->operands.ops.lhs->operands.ops.lhs);
946 mpz_eval_expr (powrhs, e->operands.ops.lhs->operands.ops.rhs);
947 mpz_eval_expr (rhs, e->operands.ops.rhs);
948 mpz_powm (r, powlhs, powrhs, rhs);
949 if (mpz_cmp_si (rhs, 0L) < 0)
957 mpz_init (lhs); mpz_init (rhs);
958 mpz_eval_expr (lhs, e->operands.ops.lhs);
959 mpz_eval_expr (rhs, e->operands.ops.rhs);
960 mpz_fdiv_r (r, lhs, rhs);
961 mpz_clear (lhs); mpz_clear (rhs);
963 #if __GNU_MP_VERSION >= 2
965 mpz_init (lhs); mpz_init (rhs);
966 mpz_eval_expr (lhs, e->operands.ops.lhs);
967 mpz_eval_expr (rhs, e->operands.ops.rhs);
968 mpz_invert (r, lhs, rhs);
969 mpz_clear (lhs); mpz_clear (rhs);
973 mpz_init (lhs); mpz_init (rhs);
974 mpz_eval_expr (lhs, e->operands.ops.lhs);
975 if (mpz_cmpabs_ui (lhs, 1) <= 0)
977 /* For 0^rhs and 1^rhs, we just need to verify that
978 rhs is well-defined. For (-1)^rhs we need to
979 determine (rhs mod 2). For simplicity, compute
980 (rhs mod 2) for all three cases. */
982 two = malloc (sizeof (struct expr));
984 mpz_init_set_ui (two->operands.val, 2L);
985 makeexp (&et, MOD, e->operands.ops.rhs, two);
986 e->operands.ops.rhs = et;
989 mpz_eval_expr (rhs, e->operands.ops.rhs);
990 if (mpz_cmp_si (rhs, 0L) == 0)
993 else if (mpz_cmp_si (lhs, 0L) == 0)
994 /* 0^y (where y != 0) is 0 */
996 else if (mpz_cmp_ui (lhs, 1L) == 0)
999 else if (mpz_cmp_si (lhs, -1L) == 0)
1000 /* (-1)^y just depends on whether y is even or odd */
1001 mpz_set_si (r, (mpz_get_ui (rhs) & 1) ? -1L : 1L);
1002 else if (mpz_cmp_si (rhs, 0L) < 0)
1007 unsigned long int cnt;
1008 unsigned long int y;
1009 /* error if exponent does not fit into an unsigned long int. */
1010 if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0)
1013 y = mpz_get_ui (rhs);
1014 /* x^y == (x/(2^c))^y * 2^(c*y) */
1015 #if __GNU_MP_VERSION >= 2
1016 cnt = mpz_scan1 (lhs, 0);
1022 if (y * cnt / cnt != y)
1024 mpz_tdiv_q_2exp (lhs, lhs, cnt);
1025 mpz_pow_ui (r, lhs, y);
1026 mpz_mul_2exp (r, r, y * cnt);
1029 mpz_pow_ui (r, lhs, y);
1031 mpz_clear (lhs); mpz_clear (rhs);
1034 error = "result of `pow' operator too large";
1035 mpz_clear (lhs); mpz_clear (rhs);
1036 longjmp (errjmpbuf, 1);
1038 mpz_init (lhs); mpz_init (rhs);
1039 mpz_eval_expr (lhs, e->operands.ops.lhs);
1040 mpz_eval_expr (rhs, e->operands.ops.rhs);
1041 mpz_gcd (r, lhs, rhs);
1042 mpz_clear (lhs); mpz_clear (rhs);
1044 #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
1046 mpz_init (lhs); mpz_init (rhs);
1047 mpz_eval_expr (lhs, e->operands.ops.lhs);
1048 mpz_eval_expr (rhs, e->operands.ops.rhs);
1049 mpz_lcm (r, lhs, rhs);
1050 mpz_clear (lhs); mpz_clear (rhs);
1054 mpz_init (lhs); mpz_init (rhs);
1055 mpz_eval_expr (lhs, e->operands.ops.lhs);
1056 mpz_eval_expr (rhs, e->operands.ops.rhs);
1057 mpz_and (r, lhs, rhs);
1058 mpz_clear (lhs); mpz_clear (rhs);
1061 mpz_init (lhs); mpz_init (rhs);
1062 mpz_eval_expr (lhs, e->operands.ops.lhs);
1063 mpz_eval_expr (rhs, e->operands.ops.rhs);
1064 mpz_ior (r, lhs, rhs);
1065 mpz_clear (lhs); mpz_clear (rhs);
1067 #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
1069 mpz_init (lhs); mpz_init (rhs);
1070 mpz_eval_expr (lhs, e->operands.ops.lhs);
1071 mpz_eval_expr (rhs, e->operands.ops.rhs);
1072 mpz_xor (r, lhs, rhs);
1073 mpz_clear (lhs); mpz_clear (rhs);
1077 mpz_eval_expr (r, e->operands.ops.lhs);
1081 mpz_eval_expr (r, e->operands.ops.lhs);
1086 mpz_eval_expr (lhs, e->operands.ops.lhs);
1087 if (mpz_sgn (lhs) < 0)
1089 error = "cannot take square root of negative numbers";
1091 longjmp (errjmpbuf, 1);
1095 #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
1097 mpz_init (lhs); mpz_init (rhs);
1098 mpz_eval_expr (lhs, e->operands.ops.lhs);
1099 mpz_eval_expr (rhs, e->operands.ops.rhs);
1100 if (mpz_sgn (rhs) <= 0)
1102 error = "cannot take non-positive root orders";
1103 mpz_clear (lhs); mpz_clear (rhs);
1104 longjmp (errjmpbuf, 1);
1106 if (mpz_sgn (lhs) < 0 && (mpz_get_ui (rhs) & 1) == 0)
1108 error = "cannot take even root orders of negative numbers";
1109 mpz_clear (lhs); mpz_clear (rhs);
1110 longjmp (errjmpbuf, 1);
1114 unsigned long int nth = mpz_get_ui (rhs);
1115 if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0)
1117 /* If we are asked to take an awfully large root order, cheat and
1118 ask for the largest order we can pass to mpz_root. This saves
1119 some error prone special cases. */
1120 nth = ~(unsigned long int) 0;
1122 mpz_root (r, lhs, nth);
1124 mpz_clear (lhs); mpz_clear (rhs);
1128 mpz_eval_expr (r, e->operands.ops.lhs);
1129 if (mpz_size (r) > 1)
1131 error = "result of `!' operator too large";
1132 longjmp (errjmpbuf, 1);
1134 mpz_fac_ui (r, mpz_get_ui (r));
1136 #if __GNU_MP_VERSION >= 2
1138 mpz_eval_expr (r, e->operands.ops.lhs);
1140 cnt = mpz_popcount (r);
1141 mpz_set_si (r, cnt);
1146 mpz_init (lhs); mpz_init (rhs);
1147 mpz_eval_expr (lhs, e->operands.ops.lhs);
1148 mpz_eval_expr (rhs, e->operands.ops.rhs);
1149 cnt = mpz_hamdist (lhs, rhs);
1150 mpz_clear (lhs); mpz_clear (rhs);
1151 mpz_set_si (r, cnt);
1156 mpz_eval_expr (r, e->operands.ops.lhs);
1157 { unsigned long int cnt;
1158 if (mpz_sgn (r) <= 0)
1160 error = "logarithm of non-positive number";
1161 longjmp (errjmpbuf, 1);
1163 cnt = mpz_sizeinbase (r, 2);
1164 mpz_set_ui (r, cnt - 1);
1168 { unsigned long int cnt;
1169 mpz_init (lhs); mpz_init (rhs);
1170 mpz_eval_expr (lhs, e->operands.ops.lhs);
1171 mpz_eval_expr (rhs, e->operands.ops.rhs);
1172 if (mpz_sgn (lhs) <= 0)
1174 error = "logarithm of non-positive number";
1175 mpz_clear (lhs); mpz_clear (rhs);
1176 longjmp (errjmpbuf, 1);
1178 if (mpz_cmp_ui (rhs, 256) >= 0)
1180 error = "logarithm base too large";
1181 mpz_clear (lhs); mpz_clear (rhs);
1182 longjmp (errjmpbuf, 1);
1184 cnt = mpz_sizeinbase (lhs, mpz_get_ui (rhs));
1185 mpz_set_ui (r, cnt - 1);
1186 mpz_clear (lhs); mpz_clear (rhs);
1191 unsigned long int t;
1193 mpz_eval_expr (lhs, e->operands.ops.lhs);
1194 t = (unsigned long int) 1 << mpz_get_ui (lhs);
1195 if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0 || t == 0)
1197 error = "too large Mersenne number index";
1199 longjmp (errjmpbuf, 1);
1202 mpz_mul_2exp (r, r, t);
1203 mpz_add_ui (r, r, 1);
1209 mpz_eval_expr (lhs, e->operands.ops.lhs);
1210 if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0)
1212 error = "too large Mersenne number index";
1214 longjmp (errjmpbuf, 1);
1217 mpz_mul_2exp (r, r, mpz_get_ui (lhs));
1218 mpz_sub_ui (r, r, 1);
1223 unsigned long int n, i;
1225 mpz_eval_expr (lhs, e->operands.ops.lhs);
1226 if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0)
1228 error = "Fibonacci index out of range";
1230 longjmp (errjmpbuf, 1);
1232 n = mpz_get_ui (lhs);
1235 #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
1238 mpz_init_set_ui (t, 1);
1245 for (i = 3; i <= n; i++)
1257 unsigned long int n;
1259 mpz_eval_expr (lhs, e->operands.ops.lhs);
1260 if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0)
1262 error = "random number size out of range";
1264 longjmp (errjmpbuf, 1);
1266 n = mpz_get_ui (lhs);
1268 mpz_urandomb (r, rstate, n);
1273 mpz_eval_expr (r, e->operands.ops.lhs);
1274 mpz_nextprime (r, r);
1278 mpz_init (lhs); mpz_init (rhs);
1279 mpz_eval_expr (lhs, e->operands.ops.lhs);
1280 mpz_eval_expr (rhs, e->operands.ops.rhs);
1282 unsigned long int k;
1283 if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0)
1285 error = "k too large in (n over k) expression";
1286 mpz_clear (lhs); mpz_clear (rhs);
1287 longjmp (errjmpbuf, 1);
1289 k = mpz_get_ui (rhs);
1290 mpz_bin_ui (r, lhs, k);
1292 mpz_clear (lhs); mpz_clear (rhs);
1298 mpz_eval_expr (r, e->operands.ops.lhs);
1299 printf ("time: %d\n", cputime () - t0);
1307 /* Evaluate the expression E modulo MOD and put the result in R. */
1309 mpz_eval_mod_expr (mpz_ptr r, expr_t e, mpz_ptr mod)
1316 mpz_init (lhs); mpz_init (rhs);
1317 mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
1318 mpz_eval_expr (rhs, e->operands.ops.rhs);
1319 mpz_powm (r, lhs, rhs, mod);
1320 mpz_clear (lhs); mpz_clear (rhs);
1323 mpz_init (lhs); mpz_init (rhs);
1324 mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
1325 mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod);
1326 mpz_add (r, lhs, rhs);
1327 if (mpz_cmp_si (r, 0L) < 0)
1328 mpz_add (r, r, mod);
1329 else if (mpz_cmp (r, mod) >= 0)
1330 mpz_sub (r, r, mod);
1331 mpz_clear (lhs); mpz_clear (rhs);
1334 mpz_init (lhs); mpz_init (rhs);
1335 mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
1336 mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod);
1337 mpz_sub (r, lhs, rhs);
1338 if (mpz_cmp_si (r, 0L) < 0)
1339 mpz_add (r, r, mod);
1340 else if (mpz_cmp (r, mod) >= 0)
1341 mpz_sub (r, r, mod);
1342 mpz_clear (lhs); mpz_clear (rhs);
1345 mpz_init (lhs); mpz_init (rhs);
1346 mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
1347 mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod);
1348 mpz_mul (r, lhs, rhs);
1349 mpz_mod (r, r, mod);
1350 mpz_clear (lhs); mpz_clear (rhs);
1354 mpz_eval_expr (lhs, e);
1355 mpz_mod (r, lhs, mod);
1362 cleanup_and_exit (int sig)
1365 #ifdef LIMIT_RESOURCE_USAGE
1367 printf ("expression took too long to evaluate%s\n", newline);
1371 printf ("divide by zero%s\n", newline);
1374 printf ("expression required too much memory to evaluate%s\n", newline);